-
Notifications
You must be signed in to change notification settings - Fork 129
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 Freebsd #102
Support Freebsd #102
Conversation
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.
Some brief comments on things changed.
@@ -26,18 +26,64 @@ use std::thread; | |||
|
|||
const MAX_FDS_IN_CMSG: u32 = 64; | |||
|
|||
const SCM_RIGHTS: c_int = 0x01; |
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.
Moved static
and const
delarations to the top
fn CMSG_ALIGN(length: size_t) -> size_t { | ||
(length + mem::size_of::<size_t>() - 1) & !(mem::size_of::<size_t>() - 1) | ||
#[cfg(target_os = "freebsd")] | ||
unsafe fn CMSG_DATA(cmsg: *mut cmsghdr) -> *mut c_void { |
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.
Ensure proper alignment. cmsg.offset(1)
on my box is the equivalent of addq 0xc, %rcx
, but it should be addq 0x10, %rcx
.
(*cmsg_buffer).cmsg_level = libc::SOL_SOCKET; | ||
(*cmsg_buffer).cmsg_type = SCM_RIGHTS; | ||
|
||
ptr::copy_nonoverlapping(fds.as_ptr(), | ||
cmsg_buffer.offset(1) as *mut c_int, | ||
CMSG_DATA(cmsg_buffer) as *mut c_int, |
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.
Use CMSG_DATA
instead of ptr::offset
@danlrobertson I'm not sure if/when I get to look at the changes in detail; so some quick comments for now:
|
@antrik thanks for the quick reply. Don't feel rushed.
|
About the CMSG_DATA, you may be interested in https://github.com/stemjail/fdpass-rs |
65c0e76
to
6e68729
Compare
@antrik: Updated to include 2 commits. fbafaf1 move static and const declarations and 6e68729 support freebsd @l0kod: per stemjail/fdpass-rs#1, it doesn't seem to be currently working on FreeBSD. Let me know if missed something. A transition to a library like fdpass-rs I think is a great idea (and the path forward), but imo that is currently outside the scope of this PR. That being said, I'm happy to look into it further if the consensus is to do so. |
@l0kod I briefly considered |
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.
Personally, I'd prefer even finer-grained commits, with changes such as "rename platform/linux
to platform/unix
", "introduce (and use) CMSG_DATA()
", "factor out new_sockaddr_un()
", "use socklen_t
", "create sockaddr
in a platform-agnostic fashion" etc. all as separate patches... But then again, I'm a confirmed perfectionist, so my standards probably shouldn't be considered normative ;-)
@@ -26,18 +26,64 @@ use std::thread; | |||
|
|||
const MAX_FDS_IN_CMSG: u32 = 64; | |||
|
|||
const SCM_RIGHTS: c_int = 0x01; |
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.
To be honest, I'm not convinced moving these defines to the top really is an improvement... Personally I prefer definitions to be close to usage, rather than strictly following formal rules such as "all const should go to the top". But I'm aware that I might be in a minority here :-(
(Also, this is a bit off-topic I guess, but I'm still wondering why this one is not defined in libc
?...)
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.
It apears as if everything from cmsg
is not defined in libc
. It definitely seems like they should be defined somewhere like libc
or nix
.
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.
libc
I'd say. libc
is for the raw FFI interfaces; while nix
is for safe wrappers around them. Using nix
to abstract all these dirty details would be nice to have, but it's a second (much bigger) step...
// The value Linux returns for SO_SNDBUF | ||
// is not the size we are actually allowed to use... | ||
// Empirically, we have to deduct 32 bytes from that. | ||
const RESERVED_SIZE: usize = 32; |
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.
Have you checked that this is actually needed on FreeBSD as well? It's the kind of thing I would have expected to be extremely system-specific...
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.
I want to say yes, but I'll double check.
#[cfg(target_os="linux")] | ||
type IovLen = usize; | ||
#[cfg(target_os="linux")] | ||
type SockLen = usize; |
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.
Can't we just use socklen_t
everywhere?
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.
That's what I was hoping. However, socklen_t:linux = u32 but msghdr.msg_controllen = size_t = usize. This works on FreeBSD though, and was what I originally did. Perhaps this is another change that should be made to libc
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, so for some reason the POSIX committee decided to abuse socklen_t
for something that is clearly not in any way related to socket address lengths; while glibc
decided to stick with the more appropriate size_t
... This is so retarded :-(
Calling the type SockLen
is very confusing though, as it has no bearing on the primary use of socklen_t
-- better call it MsgControllen
, or something along these lines. Also, it's probably better to define it as size_t
rather than usize
, to match the libc
definition.
#[cfg(target_os="linux")] | ||
type SockLen = usize; | ||
#[cfg(target_os="linux")] | ||
#[inline] |
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.
I'd leave that decision to the compiler...
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.
👍
let mut sockaddr = sockaddr_un { | ||
sun_family: libc::AF_UNIX as u16, | ||
sun_path: [ 0; 108 ], | ||
}; |
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.
I suspect we could make this code generic, by using mem::zeroed()
and then setting only the fields we need, just as we would in C? (Along with using sa_family_t
to make the cast generic -- though I wonder why AF_UNIX
isn't defined as sa_family_t
in libc
in the first place...)
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.
I'll give it a shot.
libc::strncpy(sockaddr.sun_path.as_mut_ptr(), | ||
path, | ||
sockaddr.sun_path.len() - 1); | ||
let len = mem::size_of::<sockaddr_un>() - 104 + (libc::strlen(sockaddr.sun_path.as_ptr()) as usize); |
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 doesn't look right -- copy&paste error perhaps?...
I think we could make that code (and thus the entire function) generic as well. It will be uglier than in C due to the lack of offsetof
; but it should be doable with &sockaddr.sun_path as *const as usize - &sockaddr as *const as usize
or something along these lines?...
BTW, the example in the Linux man page for using AF_UNIX
sockets just passes sizeof sockaddr_un
as the len
parameter to connect()
, rather than calculating the actual size in use... The POSIX man page for connect()
is a bit unclear what is expected here: it says "the length of the sockaddr structure pointed to by the address argument". I'd tend to assume passing the entire size is probably correct... Which will make the code simpler.
(I suggest changing this in a separate commit before the main change.)
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.
Yes, this is an error. linux
would be - 108
, while freebsd
would be - 104
@@ -953,21 +976,32 @@ fn is_socket(fd: c_int) -> bool { | |||
|
|||
// FFI stuff follows: | |||
|
|||
const SCM_RIGHTS: c_int = 0x01; | |||
#[allow(non_snake_case)] | |||
fn CMSG_LEN(length: SockLen) -> SockLen { |
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.
I don't think it's right for these functions to work on SockLen
: I'd say they should stick with size_t
; while the cast to socklen_t
would only be done by the caller while filling the actual socket structures. This feels more natural to me, and avoids a lot of unnecessary confusing casts.
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.
Agreed 👍
CMSG_ALIGN(mem::size_of::<cmsghdr>()) + length | ||
#[cfg(target_os = "linux")] | ||
unsafe fn CMSG_DATA(cmsg: *mut cmsghdr) -> *mut c_void { | ||
cmsg.offset(1) as *mut c_void |
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.
While this matches the glibc
definition of CMSG_DATA
, I think it wouldn't hurt to just use FreeBSD definition everywhere? AIUI, Linux only gets away with the simplistic definition, because sizeof cmsghdr
happens to always have the right alignment there. This is inconsistent with the other CMSG_
definitions though, which are defined in a more generic way, always explicitly doing the alignment...
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.
Didn't think about that. That would make this a bit more simplistic. I'd definitely be okay with making this change
@@ -0,0 +1,1029 @@ | |||
// Copyright 2015 The Servo Project Developers. See the COPYRIGHT |
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.
Something went wrong with your commit: it introduces both src/platform/unix/mod.rs
and src/platform/unix/linux/mod.rs
(with identical contents) in place of the original src/platform/linux/mod.rs
...
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.
I'll fix this in the update... My bad.
Thanks for the very thorough review. I'll make the changes and comment when I make the update. I'll also start looking into a better home for |
Move the static and const declarations to the top of the file
6e68729
to
7e2c42e
Compare
Updated, and I must admit you were right... It makes a lot more sense this way.
Updated.
Updated.
Updated. |
7e2c42e
to
95dccff
Compare
#[cfg(all(not(feature = "force-inprocess"), target_os = "linux"))] | ||
include!("linux/mod.rs"); | ||
#[cfg(all(not(feature = "force-inprocess"), any(target_os = "linux", | ||
target_os = "freebsd")))] |
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.
Personally, I'd add the freebsd
case only right before or along with actually adding FreeBSD-specific code, after the generic portability improvements... But this way is fine too I guess :-)
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.
Not sure what you mean by this. Do you mean use something like a all(unix,not(macos))
instead of specifying linux and freebsd for using the unix module?
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.
No, I was only referring to how changes are split up into patches, rather than the final code. (Sorry for being so pedantic about this... It's really not important; just a suggestion :-) )
Having said that, I already pondered something along the lines of what you said here. I'm honestly not sure. Normally, I'd prefer this approach indeed; but in this specific case, we need to handle each platform explicitly anyway because of the MsgControllen
ugliness :-( It might still be a win though -- especially if this can be handled at the libc
level at some point?...
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.
Updated with the suggested patch splits.
Agreed. In the future we could/should be able to get away with just unix
.
unsafe fn new_sockaddr_un(path: *const c_char) -> (sockaddr_un, usize) { | ||
let mut sockaddr: sockaddr_un = mem::zeroed(); | ||
libc::strncpy(sockaddr.sun_path.as_mut_ptr(), | ||
path, sockaddr.sun_path.len() - 1); | ||
sockaddr.sun_family = libc::AF_UNIX as u16; | ||
sockaddr.sun_family = libc::AF_UNIX as SunFamily; |
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.
Can't you just use sa_family_t
here as I suggested?...
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.
Yup. Good point.
@@ -961,7 +954,7 @@ fn CMSG_LEN(length: size_t) -> size_t { | |||
} | |||
|
|||
#[allow(non_snake_case)] | |||
fn CMSG_DATA(cmsg: *mut cmsghdr) -> *mut c_void { | |||
unsafe fn CMSG_DATA(cmsg: *mut cmsghdr) -> *mut c_void { |
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.
I think that belongs with the previous commit?...
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.
My bad
let mut sockaddr: sockaddr_un = mem::zeroed(); | ||
libc::strncpy(sockaddr.sun_path.as_mut_ptr(), | ||
path, sockaddr.sun_path.len() - 1); | ||
sockaddr.sun_family = libc::AF_UNIX as u16; |
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.
I'd split the commits a bit differently: first only split out new_sockaddr_un()
, without any change to the actual code moved in there, so it's a pure refactoring; and only after that one or more commits that actually make it platform-agnostic, by introducing mem::zeroed()
, sa_family_t
, etc.
(Not insisting though -- probably it's clear enough that way as well...)
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.
Done! in the latest batch of commits
path, sockaddr.sun_path.len() - 1); | ||
sockaddr.sun_family = libc::AF_UNIX as u16; | ||
let len = mem::size_of::<c_short>() + (libc::strlen(sockaddr.sun_path.as_ptr()) | ||
as usize); |
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.
While this happens to work on Linux and FreeBSD, I don't think it's really generic... As I said, this would probably require some pointer arithmetic -- but I still think the right way to handle this is to just use sizeof sockaddr_un
, like in the Linux man page example, rather than trying to determine the actually used size dynamically.
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.
Good point. Used sizeof(sockaddr_un)
in the latest batch of commits.
601b464
to
b9c149d
Compare
Apart from the pending question regarding handling of platform conditionals, I'd say this is good to go :-) |
Thank you for doing this work! Got Webrender working on FreeBSD :) |
Rename platform/linux to platform/unix in preparation to adding support for FreeBSD.
Instead of directly using ptr::offset and the equivalent of CMSG_DATA in glibc on Linux, create a CMSG_DATA function that should work on Linux and FreeBSD. This should not cause any side effects, but should make it easier if we should introduce support for another OS that may have a different implementation of CMSG_DATA.
Add the new_sockaddr_un function that builds a sockaddr_un struct in a platform agnostic way.
Add OS specific types that address alignment problems and their respective libc definitions.
b9c149d
to
4886205
Compare
Updated with the suggested patch splits. |
Great, let's get this landed :-) |
@bors-servo: r+ |
📌 Commit 4886205 has been approved by |
Support Freebsd Add support for FreeBSD and rename `linux` module to `unix`. **NB:** Some tests are still currently failing on freebsd. I believe most of which have to do with system limits e.g. (`platform::medium_data` blocks on a `send_followup_fragment` due to system limits and never recovers).
☀️ Test successful - status-appveyor, status-travis |
Add support for FreeBSD and rename
linux
module tounix
.NB: Some tests are still currently failing on freebsd. I believe most of which have to do with system limits e.g. (
platform::medium_data
blocks on asend_followup_fragment
due to system limits and never recovers).