Skip to content

Conversation

@cwakamo
Copy link
Member

@cwakamo cwakamo commented Aug 31, 2018

The logger entrypoints now consult a C-defined thread-local bool and exit immediately if the current thread is already logging. If the current thread is not logging, they set the bool to indicate that it is, and then unset it at the end of the function.

This allows types which reference self in their implementations of CustomPlaygroundQuickLookable or CustomStringConvertible (among other things) in such a way that self would be logged to not cause infinite recursion in the logger. It also means that logging won't log the side-effects of logging anymore.

This addresses rdar://problem/41460357 / SR-8349.

Added a thread-local `bool`, `PGLThreadIsLogging`, which is used in each of the logger entrypoints. This is defined in C as it's not possible (to my knowledge) to create a thread-local variable in Swift.
Each of the logger entrypoints first checks this value; if it's `true`, then the function returns nil. If it's `false`, then the function sets it to `true`, defers setting it back to `false`, and then generates the log packet.
This allows logging to complete successfully in cases when logging a value would cause that value to be logged (e.g. if the implementation of `CustomStringConvertible` or `CustomPlaygroundDisplayConvertible` caused `self` to be logged).

This addresses <rdar://problem/41460357> / SR-8349.
Added tests for both the new and legacy entrypoints to ensure that recursive logging does not occur.
In both cases, a struct whose implementation of `CustomStringConvertible` logs `self` is logged.
Without the changes in the previous commit, this causes infinite recursion.
With those changes, these tests pass as expected.

This is for <rdar://problem/41460357> / SR-8349.
@cwakamo cwakamo requested a review from jonathanpenn August 31, 2018 23:52
Copy link

@jonathanpenn jonathanpenn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great! I had one very minor comment on how a comment was worded. I think this is good to go.

/// logging.
///
/// This is used by the functions in LoggerEntrypoints.swift and
/// LegacyEntrypoints.swift to prevent generating log packets while in already

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very minor nit, but the way I'm reading this it seems like "...while in already..." should be "...while already...".

@jrose-apple
Copy link

@rjmccall Does Swift handle __thread variables correctly?

@rjmccall
Copy link
Member

rjmccall commented Sep 1, 2018

No, I don't think we have any logic for handling thread-locals.

@jrose-apple
Copy link

Okay. To be safe, Connor, you should write some static inline C wrappers around your __thread variable, then.

@cwakamo
Copy link
Member Author

cwakamo commented Sep 6, 2018

Ah, OK. In email @jckarter suggested that using __thread variables define in C from Swift ought to work, but I'll add some wrappers to be safe.

…d set `PGLThreadIsLogging`.

This is to insulate from any issues which might arise because Swift may or may not handle `__thread` variables correctly.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants