Skip to content

Bikeshed: name for Socket::new_with_common_flags #111

@Thomasdezeeuw

Description

@Thomasdezeeuw
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?

Activity

Thomasdezeeuw

Thomasdezeeuw commented on Oct 9, 2020

@Thomasdezeeuw
CollaboratorAuthor

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

de-vri-es

de-vri-es commented on Oct 17, 2020

@de-vri-es
Contributor

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

Thomasdezeeuw commented on Oct 18, 2020

@Thomasdezeeuw
CollaboratorAuthor

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

de-vri-es commented on Oct 18, 2020

@de-vri-es
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

Thomasdezeeuw commented on Oct 21, 2020

@Thomasdezeeuw
CollaboratorAuthor

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

de-vri-es commented on Oct 21, 2020

@de-vri-es
Contributor

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

Thomasdezeeuw commented on Oct 24, 2020

@Thomasdezeeuw
CollaboratorAuthor

@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

de-vri-es commented on Oct 24, 2020

@de-vri-es
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

de-vri-es commented on Oct 30, 2020

@de-vri-es
Contributor

Starting on implementing that suggestion in #117.

Thomasdezeeuw

Thomasdezeeuw commented on Nov 28, 2020

@Thomasdezeeuw
CollaboratorAuthor

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @de-vri-es@Thomasdezeeuw

        Issue actions

          Bikeshed: name for Socket::new_with_common_flags · Issue #111 · rust-lang/socket2