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.
diff --git a/include/proto/mworker.h b/include/proto/mworker.h
index 86f0904..2386a44 100644
--- a/include/proto/mworker.h
+++ b/include/proto/mworker.h
@@ -27,7 +27,6 @@
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 2b3cf2e..661cbd1 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -2495,7 +2495,6 @@
{
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 @@
}
}
- 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 cac7410..d5040b7 100644
--- a/src/mworker.c
+++ b/src/mworker.c
@@ -357,22 +357,29 @@
}
/*
- * 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