Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upFlush stdout on read from stdin again #25572
Conversation
rust-highfive
assigned
aturon
May 18, 2015
This comment has been minimized.
This comment has been minimized.
|
r? @aturon (rust_highfive has picked a reviewer for you, use r? to override) |
nagisa
force-pushed the
nagisa:reflush-on-stdin
branch
from
94eaae2
to
517968c
May 18, 2015
nagisa
force-pushed the
nagisa:reflush-on-stdin
branch
from
517968c
to
c0509eb
May 18, 2015
alexcrichton
added
the
T-libs
label
May 26, 2015
sfackler
reviewed
May 27, 2015
| @@ -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()); | |||
This comment has been minimized.
This comment has been minimized.
sfackler
May 27, 2015
Member
Minor nit: let _ = stdout().flush() is a bit more common than drop(stdout().flush()).
This comment has been minimized.
This comment has been minimized.
|
@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. |
This comment has been minimized.
This comment has been minimized.
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. |
This comment has been minimized.
This comment has been minimized.
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 |
This comment has been minimized.
This comment has been minimized.
|
The main counterarguments are:
I'm pretty on the fence about this one. Would be great to hear from others in @rust-lang/libs! |
This comment has been minimized.
This comment has been minimized.
|
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. |
This comment has been minimized.
This comment has been minimized.
|
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? |
This comment has been minimized.
This comment has been minimized.
|
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. |
alexcrichton
added
the
I-needs-decision
label
Jun 2, 2015
This comment has been minimized.
This comment has been minimized.
|
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! |
nagisa commentedMay 18, 2015
This is possible now since we have reentrant mutexes. Fixes #25555.