Thread
-
Re: [PATCH] Fix socket handle inheritance on Windows
Bryan Green <dbryan.green@gmail.com> — 2025-11-07T01:35:29Z
On 11/6/25 19:03, Thomas Munro wrote: > On Fri, Nov 7, 2025 at 7:53 AM Bryan Green <dbryan.green@gmail.com> wrote: >>> The socket fix adds WSA_FLAG_NO_HANDLE_INHERIT to WSASocket() in >>> pgwin32_socket(), and calls SetHandleInformation() in >>> BackendInitialize() to mark the inherited client socket non-inheritable. >>> The latter is needed because handles passed to children become >>> inheritable again on Windows. > > Right, this is a problem too and your analysis makes sense. > > - s = WSASocket(af, type, protocol, NULL, 0, WSA_FLAG_OVERLAPPED); > + s = WSASocket(af, type, protocol, NULL, 0, > + WSA_FLAG_OVERLAPPED | WSA_FLAG_NO_HANDLE_INHERIT); > > I wonder if we should control this with a new be-more-like-Unix > SOCK_CLOEXEC flag. In practice we might never want sockets created > this way to be inherited across CreateProcess, so we might always pass > SOCK_CLOEXEC in places like libpq (we already do that). But in theory > at least, someone might have a reason to want an inheritable socket > (no doubt with some complications), and it seems attractive to work > the same way cross-platform and also mirror the O_CLOEXEC behaviour > your other thread fixes, and I'm also looking further ahead to the > case of accepted sockets that have some additional needs (see below), > so it might be good to be explicit and consistent about the flags. > > +#ifdef WIN32 > + /* > + * On Windows, the client socket inherited from the postmaster becomes > + * inheritable again in this process. Prevent child processes spawned > + * by this backend from inheriting it. > + */ > + if (!SetHandleInformation((HANDLE) port->sock, HANDLE_FLAG_INHERIT, 0)) > + ereport(WARNING, > + (errmsg_internal("could not disable socket handle > inheritance: error code %lu", > + GetLastError()))); > +#endif > > On Unix we also need the equivalent, but it's in pq_init(): > > #ifndef WIN32 > > /* Don't give the socket to any subprograms we execute. */ > if (fcntl(port->sock, F_SETFD, FD_CLOEXEC) < 0) > elog(FATAL, "fcntl(F_SETFD) failed on socket: %m"); > #endif > > Would it make sense to have a socket_set_cloexec() function, following > the example of socket_set_nonblocking(), so we could harmonise the > calling code? > Yes, I think it would. > I think we'll also need an accept4() function for Windows that accepts > SOCK_CLOEXEC and converts it to WSA_FLAG_NO_HANDLE_INHERIT, now that > you've pointed this out. It's not needed for your problem report > here, and doesn't even make sense for EXEC_BACKEND by definition, but > I think we'll probably want it for multithreaded PostgreSQL on > Windows. With backends as threads, at least in one experimental > architecture with listener in the main/only sub-postmaster process, > there is a race window between ye olde accept() and > socket_set_cloexec() that leaks handles if a subprocess is created > concurrently by any thread. Adopting accept4() is pretty trivial > (something like v5-0001[1]), it just wasn't quite compelling enough to > commit before multithreading started heating up as a topic. I hadn't > previously grokked that Windows will need to be able to reach its > equivalent flag too for the reason you've pointed out. > I will look over [1]. > I mention that as context for my suggestion that we might want an > explicit SOCK_CLOEXEC flag, because it finishes up being conditional > in the accept4() case assuming that design: multi-process mode needs > it except in EXEC_BACKEND builds which have to call > socket_set_cloexit() in the exec'd child by definition, while > in-development multi-threaded mode needs it on all platforms. (The > fact that macOS alone has so far refused to implement it is a bit > annoying, and potential workarounds are expensive, but that's a topic > for another day.) > If you agree, and I think you do, I will implement the SOCK_CLOEXEC abstraction and the socket_set_cloexec helper for this. My bug fix will be the first user. I also need to handle the handles for shared memory and pipes. I will probably just write those up tonight and share for review and discussion. > [1] https://www.postgresql.org/message-id/flat/CA%2BhUKGKPNFcfBQduqof4-7C%3DavjcSfdkKBGvQoRuAvfocnvY0A%40mail.gmail.com#abe1bf9def93e897827e878aac8a6945 Thanks for your excellent review and suggestions. -- Bryan Green EDB: https://www.enterprisedb.com