Skip to content
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

Bikeshed: name for Socket::new_with_common_flags #111

Closed
Thomasdezeeuw opened this issue Oct 8, 2020 · 10 comments
Closed

Bikeshed: name for Socket::new_with_common_flags #111

Thomasdezeeuw opened this issue Oct 8, 2020 · 10 comments

Comments

@Thomasdezeeuw
Copy link
Collaborator

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?
@Thomasdezeeuw
Copy link
Collaborator Author

We should use cfg(accessible) for this once stable: rust-lang/rust#64797.

@de-vri-es
Copy link
Contributor

de-vri-es commented 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 have Socket::with_custom_flags() for the other use-cases.

@Thomasdezeeuw
Copy link
Collaborator Author

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.

@de-vri-es
Copy link
Contributor

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.

@Thomasdezeeuw
Copy link
Collaborator Author

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.

Socket::set_cloexec sets the FD_CLOEXEC flag: https://github.com/alexcrichton/socket2-rs/blob/b0f77842b3357dd571bb86b30b354bc55215f693/src/sys/unix.rs#L375-L382, so no fiddling is required.

@de-vri-es
Copy link
Contributor

de-vri-es commented 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.

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.

@Thomasdezeeuw
Copy link
Collaborator Author

@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).

@de-vri-es
Copy link
Contributor

How about raw_new()? This would also translate nicely to raw_accept() and raw_pair(), which have the same problem.

Or maybe flipped: new_raw(), accept_raw() and pair_raw().

@de-vri-es
Copy link
Contributor

Starting on implementing that suggestion in #117.

@Thomasdezeeuw
Copy link
Collaborator Author

Done in #134, new functions are called *_raw, e.g. Socket::new_raw.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants