-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
Support more than one file descriptor per UNIX socket recvmsg. #599
Support more than one file descriptor per UNIX socket recvmsg. #599
Conversation
Current coverage is 90.67% (diff: 100%)@@ trunk #599 diff @@
==========================================
Files 836 813 -23
Lines 146451 145371 -1080
Methods 0 0
Messages 0 0
Branches 12986 12834 -152
==========================================
- Hits 133569 131810 -1759
- Misses 10650 11294 +644
- Partials 2232 2267 +35
|
|
Thanks. Can you add some test coverage? |
|
(preliminary note: not sure if I should be commenting here on in the trac ticket; I'll go ahead and do it here, but please correct me if it should be done in trac) Thanks for the quick review and feedback, I'll be happy to contribute in improved test coverage given that the code is tested by the existing tests but no tests are in place to test receiving more than one file descriptor per recvmsg. Like I commented on the track ticket description, I'd appreciate some guidance. Key reasons:
I feel that a testing approach would require manually creating a socket and calling sendmsg on it with more than one file descriptor in ancilliary data and have class similar to ReceiveFileDescriptor handle the receiving side to check the results -- it seems pretty low-level. Maybe there is a better approach. Could you or anyone please share your thoughts? |
That seems like a reasonable approach. The other approach I can think of would involve changing sendFileDescriptor so that it can send more than one file descriptor at a time. As I recall, the implementation is the way it is now because we could not find a reliable way to deal with more than one file descriptor at a time. Looking at your change, I'm not sure why this was the case - it seems straightforward enough. I may be misremembering the history; it has been quite a while since this work was done. Looking at the current implementation of Testing sending and receiving separately from each other in addition to testing Twisted's own round-tripping seems like a good thing. Twisted will always follow some pattern in how it sends file descriptors. Hand-crafted sendmsg calls are the most obvious way to test other patterns that may be used by other software. |
Agreed. For now I'd rather focus on one issue at a time, deferring sendFileDescriptor changes to a future opportunity.
Also agreed - multi file descriptor passing round-trip testing will be possible once sendFileDescriptor learns that trick. As for going with handcrafted sendmsg calls, I'd ask for your guidance in one particular aspect (please correct me if I'm wrong): given that the reactor is running during the tests, which approach would you recommend to handcrafting sendmsg calls? I don't think creating a socket manually and calling sendmsg on it would be compatible with the running reactor, as that call can block... On the other hand, assuming it's possible to grab the underlying socket from a transport (not sure), calling sendmsg on that sounds like a bad idea... Another option, which I don't like much, again, is running the manual socket+sendmsg in a separate thread. I'm probably not seeing the full picture here... (I tried browsing some tests, but couldn't find any suitable example) Any recommendation? Thanks in advance, again, for some hand-holding in this -- I'd rather have a good idea of where to go before starting coding a test than going back and forth with non-guided attempts. |
I think this is actually the easiest way to go. My assumption is that the send buffer is big enough to handle anything we might want to test. If that's wrong, we might have to do something more complicated. So, if the assumption holds: Put the sockets in non-blocking mode. Write what you need to write to set up the case you want to exercise. If the write fails with some kind of buffer-full error (EWOULDBLOCK, EAGAIN, etc), error out the test and someone will just have to work harder to exercise the case. But if the write succeeds, as I assume it will (and reliably so, not just most of the time), then proceed to kick off the reactor-based work: the bytes are already in the kernel send buffer somewhere; nothing further is required on the sending side to finish the scenario. It's true this is all pretty gross low-level stuff but I'm not sure there's any avoiding that while testing sendmsg-interacting code. |
|
One question i have, is whether there is might be information being lost in the fact that multiple FDs were sent as a single message. Although, a reasonable way to handle that would be to add a new interface that accepts multiple FDs from a single message. And then, if that interface isn't provided by the protocol, fall back to the current interface and just send the FDs one-by-one. If that is the final desired solution, then that improvement can be added incrementally later. |
Yea, that's a reasonable concern. Without thinking about it too hard, a new interface with graceful fallback sounds like a reasonable solution, too. |
|
Here's the test I've come up with. Following @exarkun guidance, a socketpair is created. One end is associated with a FakeReceiver + FakeProtocol, the other end is used to call a crafted sendmsg with two FDs in ancillary data. It verifies two things and is passing on my system (let's see what CI says about other platforms):
Things I'm not sure about:
Final notes:
As before, feedback is very welcome. PS: Re-added review keyword to ticket (that is the process, correct?) |
| self.socket = skt | ||
| self.protocol = proto | ||
| def _dataReceived(self, data): | ||
| pass |
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.
adoptStreamConnect might be just as easy as this, without the abstraction violation.
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 the prompt feedback. I didn't think of that and it sounds like a very clean approach... Unfortunatelly it seems adoptStreamConnection does not support AF_UNIX sockets (and fails if I lie saying it is AF_INET!).
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 appropriate thing to do here would be to have this workaround for now, but also include a link to the "add AF_UNIX to adoptStreamConnection" ticket. I can't find one - the closest is https://twistedmatrix.com/trac/ticket/5573 which is for adoptStreamPort.
|
@exarkun, I just pushed two minor changes not related to your note: the If you recommend I setup a proper Server instead of that FakeReceiver, in the test (or some other solution), I'll happily go after that. Just point me in the right direction. Thanks. |
Ah, that sucks. There's no real reason why AF_UNIX shouldn't be supported. It looks like someone got this started but the work stalled: https://twistedmatrix.com/trac/ticket/5573 |
|
I finally got the tests to pass on Appveyor - I naively thought none of the test_unix.py would even be attempted on Windows, but that wasn't the case. As for the actual test code (and implementation, of course!), I'll standby on feedback. |
|
Alternative test approach in https://github.com/exvito/twisted/tree/8911-exvito-explore-tests
Now standing by. Thanks. :) |
|
Updated the branch following the merge from trunk by @hawkowl: AppVeyor seems to have timed out and, thus, failed. Is there any way of having it run the tests again? (other than pushing to this branch, again?) Thanks. |
|
@exvito Unfortunately appveyor is a little primitive in the way that it interacts with github; pushing is pretty much the only way to get it to fire again. However, there are always new trunk commits coming in so hopefully this time we'll get luckier with appveyor's infra ;) |
|
Since this is exactly the kind of code which is very platform-finicky, I pushed a branch into the |
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 looks like a very clean fix. Assuming we get a clean bill of health on the buildbots, it can be merged with these minor changes. @exvito - please push said changes to your branch and alert a committer that it should be merged (a full re-review would be overkill at this point).
| self.socket = skt | ||
| self.protocol = proto | ||
| def _dataReceived(self, data): | ||
| pass |
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 appropriate thing to do here would be to have this workaround for now, but also include a link to the "add AF_UNIX to adoptStreamConnection" ticket. I can't find one - the closest is https://twistedmatrix.com/trac/ticket/5573 which is for adoptStreamPort.
| @@ -382,6 +383,62 @@ def test_fileDescriptorOverrun(self): | |||
| test_fileDescriptorOverrun.skip = sendmsgSkip | |||
|
|
|||
|
|
|||
| def test_multiFileDescriptorReceivedPerRecvmsg(self): | |||
| """ | |||
| Verify that _SendmsgMixin handles receiving multiple file descriptors | |||
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.
As per https://jml.io/pages/test-docstrings.html we should remove "verify that" from the docstring.
| @@ -0,0 +1 @@ | |||
| No longer fails if recvmsg's ancilliary data contains more than one file descriptor. | |||
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.
As per http://twistedmatrix.com/trac/wiki/ReviewProcess#Newsfiles this should give a fully-qualified Python name as a subject; so, in this case, the affected public APIs would be twisted.internet.unix.Server.doRead and twisted.internet.unix.Client.doRead
…ti' into 8911-exvito-unix-fd-received-multi
|
@glyph, thanks for your input:
Lastly, per @glyph's request: dear committers, please merge this in. Thanks. |
|
Trying to figure out if this PR is "green" on platforms other than the ones tested by AppVeyor and Travis, I went looking for the buildbot results. Can one of you please help me out understanding them? I can't seem to find this PR's test in the stdio log of the builds here: https://buildbot.twistedmatrix.com/boxes-all?branch=trunk&num_builds=10 Maybe I'm looking in the wrong place or maybe I need to pick a particular build. If so, I would I know which? Thanks in advance. |
See ticket at https://twistedmatrix.com/trac/ticket/8911