Skip to content

Commit

Permalink
Merge pull request #2654 from methane/graceful-stop
Browse files Browse the repository at this point in the history
`gracefully_kill()` uses pipe to stop worker loop
  • Loading branch information
xrmx authored Sep 8, 2024
2 parents 8d3bcc2 + 71a492f commit f41c7c3
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 7 deletions.
1 change: 1 addition & 0 deletions core/loop.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
30 changes: 23 additions & 7 deletions core/uwsgi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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, ...) {
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions uwsgi.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down

0 comments on commit f41c7c3

Please sign in to comment.