GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | |||||||||||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | |||||||||||||||||||||||||||
GeezerVison is showing github.com — bpo-27456: Ensure TCP_NODELAY is set on linux by 1st1 · Pull Request #4231 · python/cpython Conversation
|
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Please end the sentence with a period. :)
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Done
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
I didn't check that you replaced all sock with sock.type, but tests pass so it should be fine :-)
LGTM.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Oops, no, Travis CI failed. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
I don't figure out why the failed test shouldn't go though fastpath |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
This change is ok. But please fix also "type == socket.SOCK_DGRAM" below, fix test_ipaddr_info(), and please also write a test for non-blocking DGRAM socket.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Ping @1st1
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated. Once you have made the requested changes, please leave a comment on this pull request containing the phrase |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
I'll work on this later today. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
socket.SOCK_STREAM is not a bit, it's a value, but socket.SOCK_NONBLOCK is a bit. That's why it is weird and complicated. Values and socket creation flags are mixed. For example, this check will fail for sock_type == socket.SOCK_SEQPACKET:
>>> (socket.SOCK_SEQPACKET & socket.SOCK_STREAM) == socket.SOCK_STREAM True
All possible values on Linux:
>>> list(socket.SocketKind) [<SocketKind.SOCK_STREAM: 1>, <SocketKind.SOCK_DGRAM: 2>, <SocketKind.SOCK_RAW: 3>, <SocketKind.SOCK_RDM: 4>, <SocketKind.SOCK_SEQPACKET: 5>, <SocketKind.SOCK_NONBLOCK: 2048>, <SocketKind.SOCK_CLOEXEC: 524288>]
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
At this point, how about switching to EAFP (Easier to Ask Forgiveness than Permission)?
try:
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
except OSError:
pass
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Yeah, that's what I'm planning to do here. There appears to be no reliable and future-proof way of checking socket type on Linux, so EAFP is the best option. The "not so good" option is to do a dance like this:
if sock.type & ~(SOCK_NONBLOCK | SOCK_CLOEXEC) == SOCK_STREAM:
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
I prefer to filter flags rather than always calling setsockopt() but ignore errors. For best performance, I prefer to avoid useless syscalls.
sock.type & ~(SOCK_NONBLOCK | SOCK_CLOEXEC)
Maybe we should add an attribute to socket.socket which returns the type without SOCK_NONBLOCK and SOCK_CLOEXEC bits.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Another option is to add SOCK_TYPE_MASK, maybe even as socket.SOCK_TYPE_MASK, as Linux does (https://github.com/torvalds/linux/blob/v4.13/include/linux/net.h#L77).
I think that
sock.type & ~(SOCK_NONBLOCK | SOCK_CLOEXEC)
is not as future-proof as
sock.type & SOCK_TYPE_MASK
Shouldn't BSD/Linux devs support backward-compatibility/conventions after introducing SOCK_CLOEXEC and SOCK_NONBLOCK flags? Maybe using SOCK_TYPE_MASK will be safe enough?
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
I like SOCK_TYPE_MASK idea. At least we can do this on Linux.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
I'll do some experiments/more digging and update this PR.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
For best performance, I prefer to avoid useless syscalls.
At the cost of maintainability, for a syscall that's called once in a socket's lifetime...
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
About being "future-proof": SOCK_NONBLOCK and SOCK_CLOEXEC flags are now old and well known. But I agree that it's annoying to have to care of them :-(
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
>>> def f(sock): ...: try: ...: sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) ...: except OSError: ...: pass ...: >>> sock = socket.socket(socket.AF_INET) >>> %timeit f(sock) 500 ns ± 18.3 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each) >>> sock = socket.socket(socket.AF_UNIX) >>> %timeit f(sock) 1.66 µs ± 6.82 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
While the idea of a new socket.socket attribute getting type without flags and SOCK_TYPE_MASK idea are nice, I suggest to keep this PR simple as the initially proposed fix, and open a new issue on bugs.python.org to propose to enhance the socket module. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
|
ping |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
I have made the requested changes; please review again |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Thanks for making the requested changes! @vstinner: please review the changes made to this pull request. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
@vstinner I think this should now be ready to be merged. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| # `sock_type == socket.SOCK_STREAM`, see | ||
| # https://github.com/torvalds/linux/blob/v4.13/include/linux/net.h#L77 | ||
| # for more details. | ||
| return (sock_type & 0xF) == socket.SOCK_STREAM |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Would it be possible to add a private constant to the socket module, rather rhan using a private constant? If available, even use the Linux constant.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
This constant can be ~0 if SOCK_NONBLOCK is missing to prevent the if.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Would it be possible to add a private constant to the socket module, rather rhan using a private constant?
Maybe, but I'd like to do that in a separate PR to the socket module first. I'd like to merge this PR as is.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
IOW -- in my opinion this PR should be merged as is and backported to 3.6. I'll work on a new PR to expose SOCK_TYPE_MASK in socket and we'll update asyncio to use that.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
I'm ok with merging, backporting to 3.6 and polishing 3.7 at the end.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
When you're done making the requested changes, leave the comment: |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
A more generic fix is in progress: https://bugs.python.org/issue32331
Yes, I'll merge this in now, and when that issue is resolved, I'll update the code for 3.7. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Thanks @1st1 for the PR 🌮🎉.. I'm working now to backport this PR to: 3.6. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Sorry, @1st1, I could not cleanly backport this to |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
(cherry picked from commit e796b2f)
|
Backport PR: #4898 |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
GH-4898 is a backport of this pull request to the 3.6 branch. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
Successfully merging this pull request may close these issues.
There was an error while loading. Please reload this page.