You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Pr #110 changed Socket::new to be a simple call to socket(2), with setting common flags like CLO_EXEC. For convenience we should add back a function which copies the old behaviour. For that function we need a good name. Some possibilities:
Socket::new_with_common_flags: too long.
Socket::like_std: create a socket like the standard library would?
Hmm, I understand the reasoning behind this, but I do think that 9 out of 10 times (if not more) you want to use the default flags.
This is probably true.
So I would actually flip this: have Socket::new() use the almost always desired flags, and have Socket::with_custom_flags() for the other use-cases.
I still argue for keeping Socket::new as a wrapper for socket(2). I see the crate socket2 as a small wrapper around the libc interface with some convenient functions added, such as Domain::for_address, and I would argue that Socket::new_with_common_flags is one of those convenience functions.
Hmm, another reason to be careful is that it will change the behavior of existing code. Currently, sockets are always created with the CLOEXEC flag set. After the change the file descriptors will be leaked to child processes if the default new() is used. Of course there is semver to signify breaking changes, but most people will just fix compilation errors rather than look in=depth what changed.
To me personally, it also feels wrong to create file descriptors without close-on-exec set by default. Leaking file descriptors is bad, so not a nice default.
Also, currently there isn't even a way to set the close-on-exec flag after creation for the user. At the very least that should be exposed for the user, so with_default_flag() doesn't do magic the user can't reproduce without fiddling with the raw fd.
Hmm, another reason to be careful is that it will change the behavior of existing code. Currently, sockets are always created with the CLOEXEC flag set. After the change the file descriptors will be leaked to child processes if the default new() is used. Of course there is semver to signify breaking changes, but most people will just fix compilation errors rather than look in=depth what changed.
To me personally, it also feels wrong to create file descriptors without close-on-exec set by default. Leaking file descriptors is bad, so not a nice default.
The thing is, in some cases that is exactly what you want. We should support cases where the child process can use the socket. To me this library should do the least surprising thing. Since the documentation says the function says it corresponds to socket(2) and WSASocketW (https://github.com/alexcrichton/socket2-rs/blob/b0f77842b3357dd571bb86b30b354bc55215f693/src/socket.rs#L106-L108), it should only call that function. That is true for all methods, but previously Socket::new was an exception and it did additional stuff (such as setting CLOEXEC).
Also, currently there isn't even a way to set the close-on-exec flag after creation for the user. At the very least that should be exposed for the user, so with_default_flag() doesn't do magic the user can't reproduce without fiddling with the raw fd.
The thing is, in some cases that is exactly what you want. We should support cases where the child process can use the socket.
Even then the proper thing to do is to disable the flag after forking, before exec-ing the new binary (or to use dup2, but still after forking). That's the only race-free way to let child processes inherit the file descriptor (atleast on platforms that have SOCK_CLOEXEC, without it nothing is race free of course).
Socket::set_cloexec sets the FD_CLOEXEC flag:
Ah, I looked on docs.rs where it doesn't show up since it isn't released yet.
Since the documentation says the function says it corresponds to socket(2) and WSASocketW, it should only call that function. That is true for all methods, but previously Socket::new was an exception and it did additional stuff (such as setting CLOEXEC).
Another exception was accept, which also set the close-on-exec flag. I still believe that setting the close-on-exec flag is important enough to warrant such an exception, and I'd rather update documentation to explain it than remove the behaviour.
And socket2 is not just a wrapper around syscalls, it's also a portability layer for different platforms. To me, that means doing the best possible thing by default on the supported platforms, and not to let the user deal with the platform differences.
@de-vri-es what you propose as function name that only calls socket(2)/WSASocketW and nothing else? I might be able to be convinced to change Socket::new to set the flags, if can come up with a better name then Socket::new_with_common_flags for the "set common flags" method (which is a terrible name).
Activity
Thomasdezeeuw commentedon Oct 9, 2020
We should use
cfg(accessible)
for this once stable: rust-lang/rust#64797.de-vri-es commentedon Oct 17, 2020
Hmm, I understand the reasoning behind this, but I do think that 9 out of 10 times (if not more) you want to use the default flags.
So I would actually flip this: have
Socket::new()
use the almost always desired flags, and haveSocket::with_custom_flags()
for the other use-cases.Thomasdezeeuw commentedon Oct 18, 2020
This is probably true.
I still argue for keeping
Socket::new
as a wrapper forsocket(2)
. I see the crate socket2 as a small wrapper around the libc interface with some convenient functions added, such asDomain::for_address
, and I would argue thatSocket::new_with_common_flags
is one of those convenience functions.de-vri-es commentedon Oct 18, 2020
Hmm, another reason to be careful is that it will change the behavior of existing code. Currently, sockets are always created with the
CLOEXEC
flag set. After the change the file descriptors will be leaked to child processes if the defaultnew()
is used. Of course there is semver to signify breaking changes, but most people will just fix compilation errors rather than look in=depth what changed.To me personally, it also feels wrong to create file descriptors without close-on-exec set by default. Leaking file descriptors is bad, so not a nice default.
Also, currently there isn't even a way to set the close-on-exec flag after creation for the user. At the very least that should be exposed for the user, so
with_default_flag()
doesn't do magic the user can't reproduce without fiddling with the raw fd.Thomasdezeeuw commentedon Oct 21, 2020
The thing is, in some cases that is exactly what you want. We should support cases where the child process can use the socket. To me this library should do the least surprising thing. Since the documentation says the function says it corresponds to
socket(2)
andWSASocketW
(https://github.com/alexcrichton/socket2-rs/blob/b0f77842b3357dd571bb86b30b354bc55215f693/src/socket.rs#L106-L108), it should only call that function. That is true for all methods, but previouslySocket::new
was an exception and it did additional stuff (such as settingCLOEXEC
).Socket::set_cloexec
sets theFD_CLOEXEC
flag: https://github.com/alexcrichton/socket2-rs/blob/b0f77842b3357dd571bb86b30b354bc55215f693/src/sys/unix.rs#L375-L382, so no fiddling is required.de-vri-es commentedon Oct 21, 2020
Even then the proper thing to do is to disable the flag after forking, before exec-ing the new binary (or to use dup2, but still after forking). That's the only race-free way to let child processes inherit the file descriptor (atleast on platforms that have
SOCK_CLOEXEC
, without it nothing is race free of course).Ah, I looked on docs.rs where it doesn't show up since it isn't released yet.
Another exception was
accept
, which also set the close-on-exec flag. I still believe that setting the close-on-exec flag is important enough to warrant such an exception, and I'd rather update documentation to explain it than remove the behaviour.And
socket2
is not just a wrapper around syscalls, it's also a portability layer for different platforms. To me, that means doing the best possible thing by default on the supported platforms, and not to let the user deal with the platform differences.Thomasdezeeuw commentedon Oct 24, 2020
@de-vri-es what you propose as function name that only calls
socket(2)
/WSASocketW
and nothing else? I might be able to be convinced to changeSocket::new
to set the flags, if can come up with a better name thenSocket::new_with_common_flags
for the "set common flags" method (which is a terrible name).de-vri-es commentedon Oct 24, 2020
How about
raw_new()
? This would also translate nicely toraw_accept()
andraw_pair()
, which have the same problem.Or maybe flipped:
new_raw()
,accept_raw()
andpair_raw()
.de-vri-es commentedon Oct 30, 2020
Starting on implementing that suggestion in #117.
Thomasdezeeuw commentedon Nov 28, 2020
Done in #134, new functions are called
*_raw
, e.g.Socket::new_raw
.