From: Witold Kręcicki Date: Tue, 3 Dec 2019 18:48:10 +0000 (+0100) Subject: netmgr: X-Git-Tag: v9.15.7~20^2~12 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0bf74ac79284688c0b1cefbf8972235a75ee51e6;p=thirdparty%2Fbind9.git netmgr: - 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 --- diff --git a/lib/isc/netmgr/netmgr-int.h b/lib/isc/netmgr/netmgr-int.h index e882f3586bf..1d7b09db328 100644 --- a/lib/isc/netmgr/netmgr-int.h +++ b/lib/isc/netmgr/netmgr-int.h @@ -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 */ diff --git a/lib/isc/netmgr/netmgr.c b/lib/isc/netmgr/netmgr.c index ab9f956b221..1216918d26d 100644 --- a/lib/isc/netmgr/netmgr.c +++ b/lib/isc/netmgr/netmgr.c @@ -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); diff --git a/lib/isc/netmgr/tcp.c b/lib/isc/netmgr/tcp.c index 22d21d57bb4..8a9eac74f1c 100644 --- a/lib/isc/netmgr/tcp.c +++ b/lib/isc/netmgr/tcp.c @@ -10,6 +10,7 @@ */ #include +#include #include #include @@ -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.