/*% Used to transfer listening TCP sockets to children */
uv_pipe_t ipc;
- char ipc_pipe_name[32];
+ char ipc_pipe_name[64];
atomic_int_fast32_t schildren;
/*% Extra data allocated at the end of each isc_nmhandle_t */
ISC_THREAD_LOCAL int isc__nm_tid_v = ISC_NETMGR_TID_UNKNOWN;
#ifdef WIN32
-#define NAMED_PIPE_PREFIX "\\\\.\\pipe\\named-ipc"
+#define NAMED_PIPE_PATTERN "\\\\.\\pipe\\named-%d-%u.pipe"
#else
-#define NAMED_PIPE_PREFIX ".named-ipc"
+#define NAMED_PIPE_PATTERN "/tmp/named-%d-%u.pipe"
#endif
static void
}
/*
- * XXXWPK Maybe it should be in tmp, maybe it should not
- * be random?
+ * Use a random number in the named pipe name. Also add getpid()
+ * to the name to make sure we don't get a conflict between
+ * different unit tests running at the same time, where the PRNG
+ * is initialized to a constant seed.
*/
- strcpy(sock->ipc_pipe_name, NAMED_PIPE_PREFIX);
- for (int i = strlen(sock->ipc_pipe_name); i < 31; i++) {
- sock->ipc_pipe_name[i] = isc_random8() % 24 + 'a';
- }
- sock->ipc_pipe_name[31] = '\0';
+ snprintf(sock->ipc_pipe_name, sizeof(sock->ipc_pipe_name),
+ NAMED_PIPE_PATTERN, getpid(), isc_random32());
+ sock->ipc_pipe_name[sizeof(sock->ipc_pipe_name) - 1] = '\0';
isc_mutex_init(&sock->lock);
isc_condition_init(&sock->cond);
*/
#include <unistd.h>
+#include <libgen.h>
#include <uv.h>
#include <isc/atomic.h>
}
}
+#ifndef WIN32
+/*
+ * Run fsync() on the directory containing a socket's IPC pipe, to
+ * ensure that all threads can see the pipe.
+ */
+static void
+syncdir(const isc_nmsocket_t *sock) {
+ char *pipe = isc_mem_strdup(sock->mgr->mctx, sock->ipc_pipe_name);
+ int fd = open(dirname(pipe), O_RDONLY);
+
+ RUNTIME_CHECK(fd >= 0);
+
+ isc_mem_free(sock->mgr->mctx, pipe);
+
+ fsync(fd);
+ close(fd);
+}
+#endif
+
/*
* For TCP listening, we create a single socket, bind it, and then
* pass it to `ncpu` child sockets - the passing is done over IPC.
r = uv_listen((uv_stream_t *) &sock->ipc, sock->nchildren,
ipc_connection_cb);
INSIST(r == 0);
-
+#ifndef WIN32
+ /*
+ * On Unices a child thread might not see the pipe yet;
+ * that happened quite often in unit tests on FreeBSD.
+ * Syncing the directory ensures that the pipe is visible
+ * to everyone.
+ * This isn't done on Windows because named pipes exist
+ * within a different namespace, not on VFS.
+ */
+ syncdir(sock);
+#endif
/*
* We launch n 'tcpchildlistener' that will receive
* sockets to be listened on over ipc.