-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
Update naming around TcpListener::from_std so that it's harder to misuse #5597
base: master
Are you sure you want to change the base?
Conversation
tokio/src/net/tcp/listener.rs
Outdated
@@ -234,12 +281,26 @@ impl TcpListener { | |||
/// from a future driven by a tokio runtime, otherwise runtime can be set | |||
/// explicitly with [`Runtime::enter`](crate::runtime::Runtime::enter) function. | |||
#[track_caller] | |||
pub fn from_std(listener: net::TcpListener) -> io::Result<TcpListener> { | |||
pub fn from_tcp_unchecked(listener: net::TcpListener) -> io::Result<TcpListener> { |
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 documentation of this method should have a bigger focus on the fact that this is an unchecked conversion. Please see from_file_unchecked
for inspiration.
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 the the fact that the underlying file descriptor might not be set to non-blocking
the only behavioral change? Even if so, this seems like reasonable naming.
(I'm assuming that's the naming feedback you're looking for.)
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 my original suggestion it would also return an error if the underlying fd is not actually a tcp socket, but we can debate whether we want that.
tokio/tests/io_driver_drop.rs
Outdated
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.
These tests seem to be related to runtime shutdown. Not sure what the idea with tcp_doesnt_block
was.
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 should fix it on all IO types if we're fixing it on one of them.
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.
Aha the trap ^^
Does the wording seem good now? (Before I update them all following the same pattern.)
There's something that makes me feel a but uneasy however: it seems like the naming doesn't make as much sense as from_std
did... from_tcp
doesn't feel explanatory enough since there is TcpStream, TcpListener...
Now to fix that we could name it TcpStream::from_tcp_stream
, however it is not as obvious in what it does as TcpFile::from_std
.
With pipe there was only File so Pipe::from_file
is explanatory enough. Also, the fact you're asserting that the file is a pipe is the main thing you're interested in in that context so it makes sense that it's named this way.
However with our function the main thing we're interested in about that function is that it goes from std to tokio.
=> How about naming it TcpFile::from_std_checked
? That's more verbose, but at least it's more self-explanatory, you understand it right away when reading code that uses it, and it makes it pretty clear that it should be renamed to from_std
in the next major release.
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.
You're right that it's a worse name than from_std
. Your other suggestions could also work, but I don't think that they are clearly better than from_tcp
.
tokio/src/net/tcp/listener.rs
Outdated
/// This sets the socket to non-blocking mode if not already done, which | ||
/// is necessary for normal operation within Tokio. |
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 sets the socket to non-blocking mode if not already done, which | |
/// is necessary for normal operation within Tokio. | |
/// This sets the socket to non-blocking mode if it isn't already non-blocking. |
tokio/src/net/tcp/listener.rs
Outdated
/// You may generally prefer using [`from_tcp`](TcpListener::from_tcp), | ||
/// which does that for you if not already done. |
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.
/// You may generally prefer using [`from_tcp`](TcpListener::from_tcp), | |
/// which does that for you if not already done. | |
/// You should usually prefer to use [`from_tcp`](TcpListener::from_tcp). |
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.
Small nit: for reference documentation, I think it's better to avoid "you". I'd rewrite this as "It may be preferable to use from_tcp
, which sets set_nonblocking
."
tokio/src/net/tcp/listener.rs
Outdated
/// Creates new `TcpListener` from a `std::net::TcpListener`. | ||
/// | ||
/// This function is deprecated because it's easy to misuse, | ||
/// and naming doesn't warn enough about it. | ||
/// | ||
/// You should typically favor using | ||
/// [`from_tcp`](TcpListener::from_tcp) instead of | ||
/// [`from_tcp_unchecked`](TcpListener::from_tcp_unchecked. | ||
/// | ||
/// This function however has the same behavior as | ||
/// [`TcpListener::from_tcp_unchecked`]. | ||
#[track_caller] | ||
#[deprecated = "Easy to misuse - use from_tcp or from_tcp_unchecked instead"] | ||
pub fn from_std(listener: net::TcpListener) -> io::Result<TcpListener> { |
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.
Another option is to just #[doc(hidden)]
this.
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.
Ah yes, didn't think about that, that avoids cluttering the doc with deprecated stuff :)
We discussed the naming issue on discord, and we decided that we would like to solve this issue via a different approach instead. For now, we suggest adding a check to |
For reference: |
Since you all seem to agree on this and I'm not attached to it being changed under the hood either (even though I think it's ultimately a better public interface), the below reasoning assumes it's not acceptable to update the behavior like savages and pretend it's backwards-compatible. Now comparing the potential solutions that have been mentioned so far for that scenario:
To my eyes it looks like the benefits of solution 3 on the long term clearly outweigh its single downside (if it's even one since resulting code would typically be more straightforward). I didn't understand from reading the previous discussions the arguments that make 1/2 better than 3.
What did I miss? PS: The only two cases I see where it wouldn't be acceptable to make
Are there any other scenarios? Which is the one that makes it unacceptable? |
There needs to be a pass-through conversion method from std types -> Tokio types. The intent of The current proposal is to:
When this is a panic, it would only slip in if the code path is not tested in CI.
Again, this would be one log line per socket passed to
Assuming you mean in release, there would be no crash because the panic would not be enabled.
Those apps would still work the same when compiled with
This does not entirely solve the issue. We also implement That said, for the record, if we were able to find a consistent way to deprecate
|
Ah I missed "debug mode". That seems to solve most points indeed.
So you think doing both would be too much dedicated code (bloat) for the relative gain between both solutions? |
If we could deprecate the trait implementation, I would be more favorable to deprecating |
Plot twist: there is no So I'm not sure how to detect whether they are configured as blocking. If that prevents the runtime warning approach, I feel like deprecating |
You can query it using |
Wonderful. That's done. I think I'm reasonably happy with the current state with regards to TcpListener. Just a few points I'd like to highlight for discussion so that they are not missed during the review:
Thanks! |
Hmm. I like the names If we're deprecating the method, then I don't think it's necessary to use |
If we deprecate, I would doc hide it. I don't love the names. What about:
|
I might prefer Sorry for adding additional alternatives to bikeshed over! :P |
I agree it's much better than |
Sounds a lot like the reasons I gave in that summary.
Also already analyzed in that same message why I think specifically AFAICT Are my messages too long? 😕 |
I can't think of any downsides other than length. They're much much more clear about what they do than
No, I think they're fine. I think the summary from 4 days ago ways very useful.
I think I probably prefer to leave the behavior of from_std unchanged, and have |
Unchanged as in "as currently implemented in this PR" or as in "as currently implemented on master, but deprecated"? (The whole point of this feature being to prevent the debugging nightmares caused by using |
As in, unchanged from master. I think deprecating (this triggers warnings) and adding alternatives is probably enough to get people to stop using it. |
So it looks like you disagree with Carl that consistency with the I agree with you but I don't think that weighs too much. Looks like you guys need to align 😉 |
Resolves #5595
Motivation
Documentation over at
tokio/tokio/src/net/tcp/listener.rs
Lines 206 to 209 in 88445e7
Solution
Providing that information in a more obvious way through the naming reduces the risk for users to spend hours tracking down nasty deadlock bugs.
TODO before merge:
Figure out the correct way to update
https://github.com/Ten0/tokio/blob/4262749c466aa55851153c7e0a6e3b992bebef37/tokio/tests/io_driver_drop.rs#L15
and
https://github.com/Ten0/tokio/blob/4262749c466aa55851153c7e0a6e3b992bebef37/tokio/tests/io_driver_drop.rs#L34
The first one seems (from the naming but I may be mistaken here) like it was meant to prevent us from what happened with that function (which originally did the check and stopped doing it as we updated mio but didn't super-notice it and did not update the doc), but it failed to deadlock as expected, so we probably want it to now test the
from_tcp
function and make it fail onfrom_tcp_unchecked
.The second one seems to follow a similar pattern so it's probably best to fix it with all the elements from the first one in mind..