bytecodealliance/rustix

Add the ability to set HANDLE_FLAG_INHERIT for Windows sockets

notgull opened this issue · 3 comments

This is basically the Windows equivalent of CLOEXEC. Two ways of going about this:

  • Add a INHERIT flag to SocketFlags on Windows.
  • Make the value for CLOEXEC on Windows be HANDLE_FLAG_INHERIT.

The second option might make more sense but also might be a footgun.

What would you think of making the ioctl_fioclex function do this?

If we make FdFlags::CLOEXEC map to this, there's a subtle semantics mismatch. fcntl_setfd sets all the flags, without the ability to set just one. There's only one flag defined today, however in theory other flags could be defined in the future. The ioctl_fioclex API sets just the close-on-exec flag, which is something the Windows API can do using the mask parameter on SetHandleInformation, so that feels like a better fit.

If we add an INHERIT flag to SocketFlags, it would obscure the fact that AFAICT Window's SetHandleInformation cannot performed atomically with the socket creation, which I think is useful to be transparent about.

rustix in general strives to avoid emulating features, and using ioctl_cloexec for Windows here would involve a small amount of what could be called emulation, however my rough sense is that it feels justified in this case because the alternative would be to expose something like a SetHandleInformation API, and rustix isn't seeking to expose Windows APIs generally, but rather just Windows APIs that are closely associated with sockets.

Does that make sense?

That sounds good, though it is possible to set it on socket creating using WSA_FLAG_NO_HANDLE_INHERIT

Cool, in that case, I think it'd also make sense to map SocketFlags::CLOEXEC to it.

Although if we do that, we should ideally find a way to make the flag work in accept_with too. Do I read the Windows docs correctly that AcceptEx takes an existing unbound socket to accept on, which could have the WSA_FLAG_NO_HANDLE_INHERIT flag set on it, providing a way to implement SocketFlags::CLOEXEC in accept_with?