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.
This commit is contained in:
Willy Tarreau 2019-05-20 11:12:15 +02:00
parent 3078e9f8e2
commit 619a95f5ad
3 changed files with 13 additions and 14 deletions

View File

@ -27,7 +27,6 @@ void mworker_catch_sigterm(struct sig_handler *sh);
void mworker_catch_sigchld(struct sig_handler *sh); void mworker_catch_sigchld(struct sig_handler *sh);
void mworker_accept_wrapper(int fd); void mworker_accept_wrapper(int fd);
void mworker_pipe_register();
void mworker_cleanlisteners(); void mworker_cleanlisteners();

View File

@ -2495,7 +2495,6 @@ static void *run_thread_poll_loop(void *data)
{ {
struct per_thread_init_fct *ptif; struct per_thread_init_fct *ptif;
struct per_thread_deinit_fct *ptdf; struct per_thread_deinit_fct *ptdf;
__decl_hathreads(static HA_SPINLOCK_T start_lock);
ha_set_tid((unsigned long)data); ha_set_tid((unsigned long)data);
tv_update_date(-1,-1); 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 /* broadcast that we are ready and wait for other threads to finish
* their initialization. * their initialization.
*/ */

View File

@ -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 (!(global.mode & MODE_MWORKER) || master)
if (fdtab[proc_self->ipc_fd[1]].iocb == mworker_accept_wrapper) return 1;
return;
if (tid != 0)
return 1;
fcntl(proc_self->ipc_fd[1], F_SETFL, O_NONBLOCK); fcntl(proc_self->ipc_fd[1], F_SETFL, O_NONBLOCK);
/* In multi-tread, we need only one thread to process /* In multi-tread, we need only one thread to process
* events on the pipe with master * 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]); fd_want_recv(proc_self->ipc_fd[1]);
return 1;
} }
REGISTER_PER_THREAD_INIT(mworker_pipe_register_per_thread);
/* ----- proxies ----- */ /* ----- proxies ----- */
/* /*
* Upon a reload, the master worker needs to close all listeners FDs but the mworker_pipe * Upon a reload, the master worker needs to close all listeners FDs but the mworker_pipe