-
Notifications
You must be signed in to change notification settings - Fork 13k
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
Expand docs/examples for TCP set_nonblocking
methods.
#45227
Conversation
r? @aturon (rust_highfive has picked a reviewer for you, use r? to override) |
9c233ee
to
8f0b531
Compare
src/libstd/net/tcp.rs
Outdated
/// This will result in `read`, `write`, `recv` and `send` operations | ||
/// becoming nonblocking, i.e. immediately returning from their calls. | ||
/// If the IO operation is successful, `Ok` is returned and no further | ||
/// action is required. If the IO operation is pending, an error with kind |
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.
Saying that the operation is pending might be a bit misleading - WouldBlock
means that the request couldn't be satisfied at that moment and you need to retry later. It's not the case that the operation's been queued up and will eventually finish.
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 mentioning this, was a little confused how it worked behind the scenes. i addressed it in 6c20fe5 but let me know if you know a better way of wording it
src/libstd/net/tcp.rs
Outdated
/// }; | ||
/// }; | ||
/// println!("number of bytes read: {}", num_bytes_read); | ||
/// println!("bytes: {:?}", buf);` |
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.
Extra `
.
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.
src/libstd/net/tcp.rs
Outdated
/// [`io::ErrorKind::WouldBlock`] is returned. | ||
/// | ||
/// On Unix platforms, calling this method corresponds to calling `fcntl`. | ||
/// On Windows calling this method corresponds to calling `ioctlsocket`. |
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 somewhat import to specify which fcntl
or ioctlsocket
is used, both fcntl
and ioctlsocket
are some kind of "catch-all" syscall that can do wildly differing things. The fcntl
FIONBIO
is used on Unix platforms and the ioctlsocket
FIONBIO
is used on Windows.
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.
addressed in c978e73
all comments have been addressed, let me know if y'all see anything else EDIT: i'll squash before review approval |
LGTM |
src/libstd/net/tcp.rs
Outdated
/// | ||
/// # Examples | ||
/// | ||
/// *Note: the usage of [busy-looping] in the following example is used |
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 feel kind of conflicted about these examples. We don't want to get too far down the epoll/IOCP rabbit hole, but it seems pretty bad for the example here to be a thing you should never do. We could maybe have some fake wait_for_more_data()
function and add something like "typically implemented via platform-specific APIs such as epoll or IOCP" into the docs?
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.
is this sorta what you mean?
diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs
index 51269d57e6..946584bcf2 100644
--- a/src/libstd/net/tcp.rs
+++ b/src/libstd/net/tcp.rs
@@ -529,7 +529,10 @@ impl TcpStream {
/// let num_bytes_read = loop {
/// match stream.read_to_end(&mut buf) {
/// Ok(b) => break b,
- /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => (),
+ /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
+ /// wait_for_fd(); // typically implemented via platform-specific
+ /// // APIs such as epoll or IOCP
+ /// }
/// Err(e) => panic!("encountered IO error: {}", e),
/// };
/// };
@@ -839,13 +842,20 @@ impl TcpListener {
/// for stream in listener.incoming() {
/// let mut stream = match stream {
/// Ok(s) => s,
- /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => continue,
+ /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
+ /// wait_for_more_data(); // typically implemented via platform-specific
+ /// // APIs such as epoll or IOCP
+ /// continue;
+ /// }
/// Err(e) => panic!("encountered IO error: {}", e),
/// };
/// loop {
/// match stream.write_all(b"foo") {
/// Ok(()) => break,
- /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => (),
+ /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
+ /// wait_for_fd(); // typically implemented via platform-specific
+ /// // APIs such as epoll or IOCP
+ /// }
/// Err(e) => panic!("encountered IO error: {}", e),
/// };
/// }
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.
Yeah, something like that seems better than nothing.
924dedb
to
1ba2f1a
Compare
@sfackler latest commit should hopefully address your concerns. i also removed the note about busy-looping now that i've added in |
src/libstd/net/tcp.rs
Outdated
/// Err(e) => panic!("encountered IO error: {}", e), | ||
/// }; | ||
/// loop { | ||
/// match stream.write_all(b"foo") { |
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.
write_all
isn't going to behave properly in a nonblocking world. If fo
was successfully written but we hit a WouldBlock
finishing the o
, everything will be sent again the next round.
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.
We'd also need to set the stream to nonblocking mode for the WouldBlock case to come up in the first place.
src/libstd/net/tcp.rs
Outdated
/// listener.set_nonblocking(true).expect("Cannot set non-blocking"); | ||
/// | ||
/// # fn wait_for_fd() { unimplemented!() } | ||
/// for stream in listener.incoming() { |
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.
Would it be simpler to just open a socket and write to it rather than also including a listener?
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.
this doc comment is forTcpListener::set_nonblocking
, so it made sense for me to include the listener. can you expand on what you mean?
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.
unless you're saying i shouldn't write to the stream. i could just read from it and print out the result. i'd also avoid the write_all
thing from your other comment
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.
Oh derp, sorry. I was thinking this was on write
for some reason...
src/libstd/net/tcp.rs
Outdated
/// # fn wait_for_fd() { unimplemented!() } | ||
/// let mut buf = vec![]; | ||
/// let num_bytes_read = loop { | ||
/// match stream.read_to_end(&mut buf) { |
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.
One last thing (sorry!) - num_bytes_read
will only contain the number of bytes read on the final call, so we probably shouldn't save it 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.
no reason to be sorry! i feel bad i'm dragging this on for you 😬
0501e46
to
97e8d00
Compare
@@ -780,17 +808,59 @@ impl TcpListener { | |||
|
|||
/// Moves this TCP stream into or out of nonblocking mode. | |||
/// | |||
/// On Unix this corresponds to calling fcntl, and on Windows this | |||
/// corresponds to calling ioctlsocket. | |||
/// This will result in `read`, `write`, `recv` and `send` operations |
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.
accept
here since it's a listener.
src/libstd/net/tcp.rs
Outdated
/// stream.set_nonblocking(true); | ||
/// let mut buf = vec![]; | ||
/// loop { | ||
/// match stream.read_to_end(&mut buf) { |
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.
This got added back?
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.
before i was doing tcp writing, this is now doing tcp reading to avoid deadling with the write_all
issue. i can remove reading/writing altogether and just grab the stream from the listener, which might make things simpler but not as realistic, but i'm not opposed
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.
One option is something like Ok(s) => handle_connection(s)
.
Looks good! Can you squash down to a single commit? r=me otherwise. |
src/libstd/net/tcp.rs
Outdated
/// match stream { | ||
/// Ok(s) => { | ||
/// // do something with the TcpStream | ||
/// handle_connection(s), |
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.
The ,
should be a ;
.
[01:04:21] ---- net/tcp.rs - net::tcp::TcpListener::set_nonblocking (line 826) stdout ----
[01:04:21] error: expected one of `.`, `;`, `?`, `}`, or an operator, found `,`
[01:04:21] --> net/tcp.rs:16:33
[01:04:21] |
[01:04:21] 16 | handle_connection(s),
[01:04:21] | ^ expected one of `.`, `;`, `?`, `}`, or an operator here
[01:04:21]
[01:04:21] thread 'rustc' panicked at 'couldn't compile the test', /checkout/src/librustdoc/test.rs:287:12
[01:04:21] note: Run with `RUST_BACKTRACE=1` for a backtrace.
[01:04:21]
[01:04:21]
[01:04:21] failures:
[01:04:21] net/tcp.rs - net::tcp::TcpListener::set_nonblocking (line 826)
439391d
to
fe3ed20
Compare
📌 Commit fe3ed20 has been approved by |
…r=sfackler Expand docs/examples for TCP `set_nonblocking` methods. Part of rust-lang#44050.
Part of #44050.