Skip to content
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

Merged
merged 1 commit into from
Oct 21, 2017

Conversation

frewsxcv
Copy link
Member

Part of #44050.

@rust-highfive
Copy link
Collaborator

r? @aturon

(rust_highfive has picked a reviewer for you, use r? to override)

/// 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
Copy link
Member

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.

Copy link
Member Author

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

/// };
/// };
/// println!("number of bytes read: {}", num_bytes_read);
/// println!("bytes: {:?}", buf);`
Copy link
Member

Choose a reason for hiding this comment

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

Extra `.

Copy link
Member Author

Choose a reason for hiding this comment

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

/// [`io::ErrorKind::WouldBlock`] is returned.
///
/// On Unix platforms, calling this method corresponds to calling `fcntl`.
/// On Windows calling this method corresponds to calling `ioctlsocket`.
Copy link
Contributor

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.

Copy link
Member Author

Choose a reason for hiding this comment

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

addressed in c978e73

@kennytm kennytm added the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Oct 13, 2017
@frewsxcv
Copy link
Member Author

frewsxcv commented Oct 14, 2017

all comments have been addressed, let me know if y'all see anything else

EDIT: i'll squash before review approval

@tbu-
Copy link
Contributor

tbu- commented Oct 14, 2017

LGTM

@kennytm kennytm added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Oct 14, 2017
@frewsxcv frewsxcv assigned QuietMisdreavus and unassigned aturon Oct 14, 2017
///
/// # Examples
///
/// *Note: the usage of [busy-looping] in the following example is used
Copy link
Member

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?

Copy link
Member Author

@frewsxcv frewsxcv Oct 19, 2017

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),
     ///         };
     ///     }

Copy link
Member

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.

@frewsxcv
Copy link
Member Author

@sfackler latest commit should hopefully address your concerns.

i also removed the note about busy-looping now that i've added in wait_for_fd();, since afaik, this is no longer busy-looping

/// Err(e) => panic!("encountered IO error: {}", e),
/// };
/// loop {
/// match stream.write_all(b"foo") {
Copy link
Member

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.

Copy link
Member

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.

/// listener.set_nonblocking(true).expect("Cannot set non-blocking");
///
/// # fn wait_for_fd() { unimplemented!() }
/// for stream in listener.incoming() {
Copy link
Member

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?

Copy link
Member Author

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?

Copy link
Member Author

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

Copy link
Member

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...

/// # fn wait_for_fd() { unimplemented!() }
/// let mut buf = vec![];
/// let num_bytes_read = loop {
/// match stream.read_to_end(&mut buf) {
Copy link
Member

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.

Copy link
Member Author

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 😬

@@ -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
Copy link
Member

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.

/// stream.set_nonblocking(true);
/// let mut buf = vec![];
/// loop {
/// match stream.read_to_end(&mut buf) {
Copy link
Member

Choose a reason for hiding this comment

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

This got added back?

Copy link
Member Author

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

Copy link
Member

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).

@sfackler
Copy link
Member

Looks good! Can you squash down to a single commit? r=me otherwise.

@kennytm kennytm added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Oct 21, 2017
/// match stream {
/// Ok(s) => {
/// // do something with the TcpStream
/// handle_connection(s),
Copy link
Member

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)

@kennytm kennytm added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Oct 21, 2017
@kennytm kennytm removed the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Oct 21, 2017
@frewsxcv
Copy link
Member Author

thanks for your patience and insight @sfackler ❤️

@bors r=sfackler rollup

@bors
Copy link
Contributor

bors commented Oct 21, 2017

📌 Commit fe3ed20 has been approved by sfackler

@kennytm kennytm added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Oct 21, 2017
frewsxcv added a commit to frewsxcv/rust that referenced this pull request Oct 21, 2017
…r=sfackler

Expand docs/examples for TCP `set_nonblocking` methods.

Part of rust-lang#44050.
bors added a commit that referenced this pull request Oct 21, 2017
Rollup of 6 pull requests

- Successful merges: #45227, #45356, #45407, #45411, #45418, #45419
- Failed merges: #45421
@bors bors merged commit fe3ed20 into rust-lang:master Oct 21, 2017
@frewsxcv frewsxcv deleted the frewsxcv-set-nonblocking branch October 21, 2017 16:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants