Conversation
| /// [`unix(7)`](http://man7.org/linux/man-pages/man7/unix.7.html) man page. | ||
| // FIXME: When `#[repr(transparent)]` is stable, use it on `UnixCredentials` | ||
| // and put that in here instead of a raw ucred. | ||
| pub enum ControlMessageOwned { |
There was a problem hiding this comment.
Per my previous comment, I think this is the wrong way to go, as it incurs avoidable heap allocation and copying.
There was a problem hiding this comment.
I chose to go this path because it's closer to backwards-compatible. I tried the 100% backwards-compatible method first, but the code got very ugly very quick, and it involved even more copying.
There was a problem hiding this comment.
It seems to be that you've settled on the worst of both worlds: both a breaking change and inefficient.
There was a problem hiding this comment.
Can you suggest something more efficient that causes no more pain for existing users? This solution, while not exactly backwards compatible, only requires a simple search and replace.
There was a problem hiding this comment.
I don't think the current specific level of breakage makes sense as a line in the sand that cannot be crossed by a single step. That said, you could compromise by only using the flyweight pattern where heap allocation is otherwise necessary, i.e. in ScmRights, though this would make "Owned" no longer an accurate descriptor.
There was a problem hiding this comment.
But what's to say that ScmRights's payload is aligned on all platforms that Nix will ever support? I don't think that's guaranteed, especially if a user ever passes an unaligned msg_control field to recvmsg.
There was a problem hiding this comment.
That's why I said "flyweight pattern" and not "a slice", yes. Refer to the comment I linked for an example implementation.
| /// let _ = cmsg_space!(RawFd, TimeVal); | ||
| /// ``` | ||
| // Unfortunately, CMSG_SPACE isn't a const_fn, or else we could return a | ||
| // stack-allocated array. |
There was a problem hiding this comment.
Could this be corrected? This seems like exactly the special case that const fns can already handle gracefully, and is the intended use of the C macros.
There was a problem hiding this comment.
The libc people are resistant to that kind of change. rust-lang/libc#1213 (actually that's a separate issue). The cmsg functions can't be made const because that requires rustc 1.31.0. libc guarantees support for 1.13.0.
| /// // Create a buffer big enough for a `ControlMessageOwned::ScmRights` message | ||
| /// // and a `ControlMessageOwned::ScmTimestamp` message | ||
| /// let _ = cmsg_space!(RawFd, TimeVal); | ||
| /// ``` |
| // The number of bytes received. | ||
| pub bytes: usize, | ||
| cmsg_buffer: &'a [u8], | ||
| cmsghdr: *const cmsghdr, |
There was a problem hiding this comment.
Because there are only three things we're going to do with that member. Pass it to CMSG_NXTHDR and CMSG_DATA, which expect pointere, and do some raw pointer arithmetic in decode_from. So no sense converting it to a reference when we'd just have to convert it back again.
There was a problem hiding this comment.
References can convert to pointers implicitly, and the PhantomData would be rendered unnecessary.
There was a problem hiding this comment.
As a matter of fact, this turned out to be pretty easy. I'll do it.
|
Thanks for your work on the libc macros, by the way! |
|
The QEMU failures are due to a bug in QEMU itself. For once I'm sure of it. The emulated recvmsg is writing beyond the end of the supplied msg_control buffer. I think it's probably due to the linked qemu bug, which is already fixed. I'll disable the test. Once japaric/cross updates its image to use qemu 2.12.0, then we can reenable it. |
|
Sigh. Travis got confused somehow and thinks I'm missing a merge commit. I guess I may as well rebase. |
55b67b0 to
55e28c7
Compare
|
I'm going to go ahead and merge this. @Ralith if you're still concerned, then please submit a separate PR to reduce data copies. |
2125d63 to
f11fe7f
Compare
|
bors r+ |
Merge conflict (retrying...) |
Merge conflict |
Our hand-rolled logic had subtle alignment bugs that caused test_scm_rights to fail on OpenBSD (and probably could cause problems on other platforms too). Using cmsg(3) is much cleaner, shorter, and more portable. No user-visible changes.
There were two problems: 1) It would always return Ok, even on error 2) It could panic if there was an error, because sockaddr_storage_to_addr would be called on uninitialized memory.
CmsgSpace had three problems: 1) It would oversize buffers that expect multiple control messages 2) It didn't use the libc CMSG_SPACE(3) macro, so it might actually undersize a buffer for a single control message. 3) It could do bad things on drop, if you instantiate it with a type that implements Drop (which none of the currently supported ControlMessage types do). Fixes nix-rust#994
On some platforms the alignment of cmsg_data could be less than the
alignment of the messages that it contains. That led to unaligned
reads
on those platforms. This change fixes the issue by always copying the
message contents into aligned objects. The change is not 100%
backwards
compatible when using recvmsg. Users may have to replace code like
this:
```rust
if let ControlMessage::ScmRights(&fds) = cmsg {
```
with this:
```rust
if let ControlMessageOwned::ScmRights(fds) = cmsg {
```
Fixes nix-rust#999
This was an oversight from PR nix-rust#1002
|
bors r+ |
I don't actually use Nix at present, so I'm just going to stick with my current implementation that doesn't have these issues. |
Build succeeded
|
It was leftover from internal churn during PR nix-rust#1020.
It was leftover from internal churn during PR nix-rust#1020.
It was leftover from internal churn during PR nix-rust#1020.
This PR fixes multiple bugs in the cmsg code.
Fixes #994
Fixes #999
Fixes #1013