-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Console.Unix: avoid deadlock between LazyInitializer and Console.Out #34297
Merged
Merged
Changes from 25 commits
Commits
Show all changes
32 commits
Select commit
Hold shift + click to select a range
d0f5dc1
Console.Unix: avoid deadlock between LazyInitializer and Console.Out
tmds fae6ccb
Add assert for InternalSyncObject
tmds 1ff6d97
Console: use Interlocked for lazy initialization
tmds 69473a8
Cleanup unused 'using'
tmds d2b4e91
Limit locking to event handlers
tmds c4c09c2
Fix AllowNull -> NotNull
tmds 7de5274
Localize LazyInitializer.EnsureInitialized logic
tmds af57dde
Remove lazy initialize delegates
tmds d5bf05f
Use static local functions for initializing
tmds 2043770
Remove unused EnsureInitializedDisposableCore
tmds 008d833
Remove unused arg from EnsureInitializedStdInReader
tmds 8e0b37f
Also EnsureInitialize when not redirected
tmds dc533a7
Dispose Console Streams with their Reader/Writer
tmds 3080288
Fix s_out -> s_error
tmds 77c2c2f
leaveOpen streams, fix Encoding set race
tmds 0f48a86
Fix races between Encoding en initializers of In/Out/Error
tmds f4656f0
Remove EnsureInitialized
tmds 73d24c4
Cleanup
tmds 5b1f471
Rename static local initializer functions to EnsureInitialized
tmds 3500753
Use lock in Input/OutputEncoding
tmds 614f621
Rename InternalSyncObject to s_syncObject
tmds 1fe70bd
Cleanup space
tmds 10ae846
Fix _isStdErrRedirected -> _isStdInRedirected
tmds f07e5ce
Remove space
tmds dcf7116
Improve comments
tmds b61ee9c
Fix potential CancelKeyPress deadlock
tmds 705b104
Apply suggestions from code review
tmds 33d5b5c
Remove unnecessary null forgiving
tmds 61349ef
Add comment about why we're not Disposing StdInReader
tmds f19a34b
Add Volatile.Writes for Volatile.Read fields
tmds f009a74
More Volatile.Writes
tmds a633fdc
Add back lock to SetIn
tmds File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Technically according to ECMA the write to s_in should be volatile as well, but coreclr doesn't require that (I assume mono, too?) and we don't consistently do it everywhere we lazily initialize.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Out of interest: does ECMA say there is a full fence at the lock exit? Isn't that enough?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a store release on lock exit. But if the s_in object reference gets published prior to writes that fully construct that published object, that could be visible before even exiting the lock, and readers can read that reference without taking the lock in the current set up.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting! I had never thought of that.
Should I add
Volatile.Write
where needed for ECMA?Does it not require this specifically when storing references for new objects? Or more general on writes to memory?
Is this behavior architecture specific?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@stephentoub I still have some open questions here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting. This means the
Volatile.Reads
in this PR aren't needed?And when a method reads the same reference that is stored on heap multiple times, the JIT/compiler aren't allowed to re-use the values from a local?
Is this ECMA spec? Or coreclr implementation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In .NET Core mode MonoVM follows coreclr memory model.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is a good idea to use
Volatile.Read/Write
in lock-free code as a form of documentation.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did not have a chance to look at the PR in details.
My general view on this is that pairing read fences with write fences is a good practice. If there was a need for a write fence, it is likely there is a need for a read fence. Unpaired fencing is relatively easy to spot and often requires explanation.
Extra read fences do not hurt much. They may interfere with code clarity or become full fences on ARM32, although the platform has been a bit on the downhill lately.
By default, I'd keep read/write fence symmetry, or add comments why not needed.
Having said that, I'd support a policy change for not using fences for publication purpose. That is the case where we already have a paired fence. (including Mono, it seems)
Having too many fences could be a distraction from the cases where fencing is actually needed and requires extraordinary care.
In cases where fencing is actually needed, it could be a good practice to add a comment "need to write Y after writing X".
From my experience - The person who reads or makes changes to the code can see that you are ordering the write of Y. But ordering relative to what?
Even if that person is you, just a few weeks later, you may find it valuable to have a comment about X. When a read fence is paired symmetrically, having the comment just on the write side could be enough.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for explaining!
I'll add the
Volatile.Write
and keep the correspondingVolatile.Read
in place.