From 619a95f5ad090d2ed6195dd794b244ebe6a9317d Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Mon, 20 May 2019 11:12:15 +0200 Subject: [PATCH] MEDIUM: init/mworker: make the pipe register function a regular initcall Now that we have the guarantee that init calls happen before any other thread starts, we don't need anymore the workaround installed by commit 1605c7ae6 ("BUG/MEDIUM: threads/mworker: fix a race on startup") and we can instead rely on a regular per-thread initcall for this function. It will only be performed on worker thread #0, the other ones and the master have nothing to do, just like in the original code that was only moved to the function. --- include/proto/mworker.h | 1 - src/haproxy.c | 7 ------- src/mworker.c | 19 +++++++++++++------ 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/include/proto/mworker.h b/include/proto/mworker.h index 86f09049f..2386a445a 100644 --- a/include/proto/mworker.h +++ b/include/proto/mworker.h @@ -27,7 +27,6 @@ void mworker_catch_sigterm(struct sig_handler *sh); void mworker_catch_sigchld(struct sig_handler *sh); void mworker_accept_wrapper(int fd); -void mworker_pipe_register(); void mworker_cleanlisteners(); diff --git a/src/haproxy.c b/src/haproxy.c index 2b3cf2ebf..661cbd1c1 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -2495,7 +2495,6 @@ static void *run_thread_poll_loop(void *data) { struct per_thread_init_fct *ptif; struct per_thread_deinit_fct *ptdf; - __decl_hathreads(static HA_SPINLOCK_T start_lock); ha_set_tid((unsigned long)data); tv_update_date(-1,-1); @@ -2511,12 +2510,6 @@ static void *run_thread_poll_loop(void *data) } } - if ((global.mode & MODE_MWORKER) && master == 0) { - HA_SPIN_LOCK(START_LOCK, &start_lock); - mworker_pipe_register(); - HA_SPIN_UNLOCK(START_LOCK, &start_lock); - } - /* broadcast that we are ready and wait for other threads to finish * their initialization. */ diff --git a/src/mworker.c b/src/mworker.c index cac74102c..d5040b759 100644 --- a/src/mworker.c +++ b/src/mworker.c @@ -357,22 +357,29 @@ void mworker_accept_wrapper(int fd) } /* - * This function register the accept wrapper for the sockpair of the master worker + * This function registers the accept wrapper for the sockpair of the master + * worker. It's only handled by worker thread #0. Other threads and master do + * nothing here. It always returns 1 (success). */ -void mworker_pipe_register() +static int mworker_pipe_register_per_thread() { - /* The iocb should be already initialized with listener_accept */ - if (fdtab[proc_self->ipc_fd[1]].iocb == mworker_accept_wrapper) - return; + if (!(global.mode & MODE_MWORKER) || master) + return 1; + + if (tid != 0) + return 1; fcntl(proc_self->ipc_fd[1], F_SETFL, O_NONBLOCK); /* In multi-tread, we need only one thread to process * events on the pipe with master */ - fd_insert(proc_self->ipc_fd[1], fdtab[proc_self->ipc_fd[1]].owner, mworker_accept_wrapper, 1); + fd_insert(proc_self->ipc_fd[1], fdtab[proc_self->ipc_fd[1]].owner, mworker_accept_wrapper, tid_bit); fd_want_recv(proc_self->ipc_fd[1]); + return 1; } +REGISTER_PER_THREAD_INIT(mworker_pipe_register_per_thread); + /* ----- proxies ----- */ /* * Upon a reload, the master worker needs to close all listeners FDs but the mworker_pipe