Skip to content

Commit 34b0b24

Browse files
committed
util: Clear FD_CLOEXEC on child socket before exec
Explicitly clear FD_CLOEXEC on the child's socket before calling exec, so the fd survives into the spawned process regardless of how the socket was created. Previously this relied on socketpair() not setting FD_CLOEXEC by default, which is not guaranteed if the caller creates sockets with SOCK_CLOEXEC or if the flag gets set by other means.
1 parent 9a0bf73 commit 34b0b24

1 file changed

Lines changed: 11 additions & 1 deletion

File tree

src/mp/util.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
#include <pthread.h>
1616
#include <sstream>
1717
#include <string>
18-
#include <sys/types.h>
18+
#include <fcntl.h>
1919
#include <sys/resource.h>
2020
#include <sys/socket.h>
2121
#include <sys/wait.h>
@@ -158,6 +158,16 @@ std::tuple<ProcessId, SocketId> SpawnProcess(ConnectInfoToArgsFn&& connect_info_
158158
}
159159
}
160160

161+
// Explicitly clear FD_CLOEXEC on the child's socket before calling
162+
// exec, so the fd survives into the spawned process regardless of how
163+
// the socket was created.
164+
int flags = fcntl(fds[0], F_GETFD);
165+
if (flags == -1) throw std::system_error(errno, std::system_category(), "fcntl F_GETFD");
166+
if (flags & FD_CLOEXEC) {
167+
flags &= ~FD_CLOEXEC;
168+
if (fcntl(fds[0], F_SETFD, flags) == -1) throw std::system_error(errno, std::system_category(), "fcntl F_SETFD");
169+
}
170+
161171
execvp(argv[0], argv.data());
162172
// NOTE: perror() is not async-signal-safe; calling it here in a
163173
// post-fork child may deadlock in multithreaded parents.

0 commit comments

Comments
 (0)