-
Notifications
You must be signed in to change notification settings - Fork 13.2k
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
Flush stdout on read from stdin again #25572
Conversation
r? @aturon (rust_highfive has picked a reviewer for you, use r? to override) |
This is possible now since we have reentrant mutexes. Fixes rust-lang#25555.
@@ -165,6 +165,9 @@ impl Stdin { | |||
#[stable(feature = "rust1", since = "1.0.0")] | |||
impl Read for Stdin { | |||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { | |||
// Flush stdout so that weird issues like a print!'d prompt not being | |||
// shown until after the user hits enter. | |||
drop(stdout().flush()); |
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.
Minor nit: let _ = stdout().flush()
is a bit more common than drop(stdout().flush())
.
@nagisa Sorry for the long delay on this review! I have a few concerns. What's the rationale for restricting this change to the Have you thought much about the potential for deadlock, given that you can actually acquire the lock for I'm not sure that's a blocker per se, but definitely seems like a concern. |
Note, that all this patch does is really reverting #23087.
Similarly, this is just a revert of functionality available previously. I believe @alexcrichton would know better about why only
Deadlock is indeed a possibility and I don’t see us ever being able to avoid it fully if we want to implement something like this. Before it was very easy to cause the deadlock, which was a strong motivator to remove flushing; People are having issues with status quo now and might actually prefer occasional deadlocks to lack of hand holding. |
One key difference is that it was previously flushing inside of
I agree, and I personally also viewed the removal in #23087 as a stance that "we're not ever going to do this" as silent locking behind the scenes is inevitably going to trip some up and be difficult to debug. My own opinion is that this is not what the standard library should be doing, and instead it needs to be (and maybe already is) clearly documented about the buffering that the standard input/output streams do so users are aware of the need to flush. I would not be ready to say that 100% of users of |
The main counterarguments are:
I'm pretty on the fence about this one. Would be great to hear from others in @rust-lang/libs! |
I'm more inclined for the conservative approach here: don't flush stdout when reading from stdin. It seems incredibly surprising to me that this would be default behavior. I do recognize that not flushing can also lead to surprising behavior based on experience with other languages. But I think Rust leans more toward the explicit end of things and flushing stdout when reading stdin leans more toward the implicit end of things IMO. |
We could avoid the deadlock issues by having one reentrant lock around both stdin and stdout (might as well throw stderr in as well at that point). I don't think it'd cause contention issues in reasonable code but I guess it's possible? |
The idea of only one reentrant lock actually isn't so bad I think. I'm still a little uncomfortable with the reads-always-flush-no-matter-what behavior, but I believe that I could come to live with it as once you've already got a lock the overhead should be fairly negligible. |
It's looking like the consensus here is leaning more towards not taking this change, largely because of the surprising locking behavior. It's also unclear how much the standard library should be doing in this regard in terms of being as "systemsy" as possible where each operation has a clear implementation (after assuming the buffering/locking necessary, however). Additionally, the use case this is fixing doesn't quite seem to be worth the cost. I also think that @sfackler's idea for one global lock can also lead to surprising deadlocks, for example if one conceptually thinks of stdout/stdin being separately locked then it's possible to get into a deadlock when mixing another resource's lock. For these reasons I'm going to close this for now, but I would encourage you to write up a discuss post if you want to pursue this to gauge the general opinion of others to see if this is a desirable change and what the possible impact could be. Regardless, though, thanks again for the PR! |
This is possible now since we have reentrant mutexes. Fixes #25555.