From 71a492f50f1479b4aeaaeef96993feb2869ba110 Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Mon, 8 Jul 2024 08:11:52 +0000 Subject: [PATCH] gracefully_kill() uses pipe to stop worker loop --- core/loop.c | 1 + core/uwsgi.c | 30 +++++++++++++++++++++++------- uwsgi.h | 2 ++ 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/core/loop.c b/core/loop.c index 8c64279bc..c6824edf2 100644 --- a/core/loop.c +++ b/core/loop.c @@ -127,6 +127,7 @@ void *simple_loop_run(void *arg1) { int main_queue = event_queue_init(); uwsgi_add_sockets_to_queue(main_queue, core_id); + event_queue_add_fd_read(main_queue, uwsgi.loop_stop_pipe[0]); if (uwsgi.signal_socket > -1) { event_queue_add_fd_read(main_queue, uwsgi.signal_socket); diff --git a/core/uwsgi.c b/core/uwsgi.c index 9bcfe15ab..3a6d9da76 100755 --- a/core/uwsgi.c +++ b/core/uwsgi.c @@ -1255,16 +1255,17 @@ void gracefully_kill(int signum) { uwsgi_log("Gracefully killing worker %d (pid: %d)...\n", uwsgi.mywid, uwsgi.mypid); uwsgi.workers[uwsgi.mywid].manage_next_request = 0; + if (uwsgi.threads > 1) { - struct wsgi_request *wsgi_req = current_wsgi_req(); - wait_for_threads(); - if (!uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].in_request) { - if (uwsgi.workers[uwsgi.mywid].shutdown_sockets) - uwsgi_shutdown_all_sockets(); - exit(UWSGI_RELOAD_CODE); + // Stop event_queue_wait() in other threads. + // We use loop_stop_pipe only in threaded workers to avoid + // unintensional behavior changes in single threaded workers. + int fd; + if ((fd = uwsgi.loop_stop_pipe[1]) > 0) { + close(fd); + uwsgi.loop_stop_pipe[1] = 0; } return; - // never here } // still not found a way to gracefully reload in async mode @@ -1296,6 +1297,17 @@ static void simple_goodbye_cruel_world(const char *reason) { // Avoid showing same message from all threads. uwsgi_log("...The work of process %d is done (%s). Seeya!\n", getpid(), (reason != NULL ? reason : "no reason given")); } + + if (uwsgi.threads > 1) { + // Stop event_queue_wait() in other threads. + // We use loop_stop_pipe only in threaded workers to avoid + // unintensional behavior changes in single threaded workers. + int fd; + if ((fd = uwsgi.loop_stop_pipe[1]) > 0) { + close(fd); + uwsgi.loop_stop_pipe[1] = 0; + } + } } void goodbye_cruel_world(const char *reason_fmt, ...) { @@ -3641,6 +3653,10 @@ void uwsgi_ignition() { exit(1); } } + if (pipe(&uwsgi.loop_stop_pipe[0])) { + uwsgi_error("pipe()") + exit(1); + } // mark the worker as "accepting" (this is a mark used by chain reloading) uwsgi.workers[uwsgi.mywid].accepting = 1; diff --git a/uwsgi.h b/uwsgi.h index 39c3282db..748bc856a 100755 --- a/uwsgi.h +++ b/uwsgi.h @@ -2953,6 +2953,8 @@ struct uwsgi_server { struct uwsgi_buffer *websockets_continuation_buffer; uint64_t max_worker_lifetime_delta; + // This pipe is used to stop event_queue_wait() in threaded workers. + int loop_stop_pipe[2]; }; struct uwsgi_rpc {