]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
netmgr:
authorWitold Kręcicki <wpk@isc.org>
Tue, 3 Dec 2019 18:48:10 +0000 (19:48 +0100)
committerWitold Kręcicki <wpk@isc.org>
Mon, 9 Dec 2019 20:43:45 +0000 (21:43 +0100)
 - make tcp listening IPC pipe name saner
 - put the pipe in /tmp on unices
 - add pid to the pipe name to avoid conflicts between processes
 - fsync directory in which the pipe resides to make sure that the
   child threads will see it and be able to open it

lib/isc/netmgr/netmgr-int.h
lib/isc/netmgr/netmgr.c
lib/isc/netmgr/tcp.c

index e882f3586bfbad31304b6d5bde7120fcfa6fa12d..1d7b09db328647489b946958ab4d6d83ed669da7 100644 (file)
@@ -339,7 +339,7 @@ struct isc_nmsocket {
 
        /*% 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 */
index ab9f956b221b62b6eb7d9866f9ec47872ed6e873..1216918d26dd60a05783c6fcdb8fc9b8045424b2 100644 (file)
@@ -44,9 +44,9 @@
 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
@@ -840,14 +840,14 @@ isc__nmsocket_init(isc_nmsocket_t *sock, isc_nm_t *mgr,
        }
 
        /*
-        * 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);
index 22d21d57bb4fbd45bac20a5033a1d2e858f743c0..8a9eac74f1c4f06253dfc135a150b793e32dc46a 100644 (file)
@@ -10,6 +10,7 @@
  */
 
 #include <unistd.h>
+#include <libgen.h>
 #include <uv.h>
 
 #include <isc/atomic.h>
@@ -203,6 +204,25 @@ isc_nm_listentcp(isc_nm_t *mgr, isc_nmiface_t *iface,
        }
 }
 
+#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.
@@ -274,7 +294,17 @@ isc__nm_async_tcplisten(isc__networker_t *worker, isc__netievent_t *ievent0) {
        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.