diff --git a/master.c b/master.c index 8d4e32cc..3545c83b 100644 --- a/master.c +++ b/master.c @@ -13,6 +13,31 @@ void uwsgi_restore_auto_snapshot(int signum) { } +void suspend_resume_them_all(int signum) { + + int i; + int suspend = 0; + + if (uwsgi.workers[0].suspended == 1) { + uwsgi_log_verbose("*** (SIGWINCH received) resuming workers ***\n"); + uwsgi.workers[0].suspended = 0; + } + else { + uwsgi_log_verbose("*** PAUSE (press start to resume, if you do not have a joypad send SIGWINCH) ***\n"); + suspend = 1; + uwsgi.workers[0].suspended = 1; + } + + for(i=1;i<=uwsgi.numproc;i++) { + uwsgi.workers[i].suspended = suspend; + if (uwsgi.workers[i].pid > 0) { + if (kill(uwsgi.workers[i].pid, SIGWINCH)) { + uwsgi_error("kill()"); + } + } + } +} + void expire_rb_timeouts(struct rb_root *root) { time_t current = time(NULL); @@ -308,6 +333,7 @@ int master_loop(char **argv, char **environ) { uwsgi.current_time = time(NULL); + uwsgi_unix_signal(SIGWINCH, suspend_resume_them_all); uwsgi_unix_signal(SIGHUP, grace_them_all); if (uwsgi.die_on_term) { uwsgi_unix_signal(SIGTERM, kill_them_all); diff --git a/master_utils.c b/master_utils.c index 10d0f998..0caf3e58 100644 --- a/master_utils.c +++ b/master_utils.c @@ -109,6 +109,7 @@ int uwsgi_respawn_worker(int wid) { uwsgi.workers[uwsgi.mywid].manage_next_request = 1; uwsgi.workers[uwsgi.mywid].cheaped = 0; uwsgi.workers[uwsgi.mywid].busy = 0; + uwsgi.workers[uwsgi.mywid].suspended = 0; uwsgi.workers[uwsgi.mywid].sig = 0; // reset the apps count with a copy from the master @@ -345,6 +346,9 @@ void uwsgi_send_stats(int fd) { if (uwsgi.workers[i + 1].cheaped) { fprintf(output,"\"status\": \"cheap\", "); } + else if (uwsgi.workers[i + 1].suspended) { + fprintf(output,"\"status\": \"pause\", "); + } else { if (uwsgi.workers[i + 1].sig) { fprintf(output,"\"status\": \"sig%d\", ", uwsgi.workers[i + 1].signum); diff --git a/plugins/python/uwsgi_pymodule.c b/plugins/python/uwsgi_pymodule.c index f7df7a09..f3d95f83 100644 --- a/plugins/python/uwsgi_pymodule.c +++ b/plugins/python/uwsgi_pymodule.c @@ -2576,6 +2576,9 @@ PyObject *py_uwsgi_workers(PyObject * self, PyObject * args) { if (uwsgi.workers[i + 1].cheaped) { zero = PyString_FromString("cheap"); } + else if (uwsgi.workers[i + 1].suspended) { + zero = PyString_FromString("pause"); + } else { if (uwsgi.workers[i + 1].sig) { zero = PyString_FromFormat("sig%d",uwsgi.workers[i + 1].signum); diff --git a/utils.c b/utils.c index 2a9d4cab..d961aa8f 100644 --- a/utils.c +++ b/utils.c @@ -747,6 +747,16 @@ void wsgi_req_setup(struct wsgi_request *wsgi_req, int async_id, struct uwsgi_so uwsgi.core[wsgi_req->async_id]->in_request = 0; uwsgi.workers[uwsgi.mywid].busy = 0; + + // now check for suspend request + if (uwsgi.workers[uwsgi.mywid].suspended == 1) { + uwsgi_log_verbose("*** worker %d suspended ***\n", uwsgi.mywid); +cycle: + // wait for some signal (normally SIGWINCH) or 10 seconds (as fallback) + (void) poll(NULL, 0, 10*1000); + if (uwsgi.workers[uwsgi.mywid].suspended == 1) goto cycle; + uwsgi_log_verbose("*** worker %d resumed ***\n", uwsgi.mywid); + } } #ifdef UWSGI_ASYNC diff --git a/uwsgi.c b/uwsgi.c index 35a0e3d7..892810ce 100644 --- a/uwsgi.c +++ b/uwsgi.c @@ -61,6 +61,9 @@ static struct option long_base_options[] = { {"daemonize", required_argument, 0, 'd'}, {"stop", required_argument, 0, LONG_ARGS_STOP}, {"reload", required_argument, 0, LONG_ARGS_RELOAD}, + {"pause", required_argument, 0, LONG_ARGS_PAUSE}, + {"suspend", required_argument, 0, LONG_ARGS_PAUSE}, + {"resume", required_argument, 0, LONG_ARGS_PAUSE}, {"listen", required_argument, 0, 'l'}, {"max-vars", required_argument, 0, 'v'}, {"buffer-size", required_argument, 0, 'b'}, @@ -3375,6 +3378,9 @@ static int manage_base_opt(int i, char *optarg) { case LONG_ARGS_RELOAD: signal_pidfile(SIGHUP, optarg); exit(0); + case LONG_ARGS_PAUSE: + signal_pidfile(SIGWINCH, optarg); + exit(0); case LONG_ARGS_ATTACH_DAEMON: if (uwsgi.startup_daemons_cnt < MAX_DAEMONS) { uwsgi.startup_daemons[uwsgi.startup_daemons_cnt] = optarg; diff --git a/uwsgi.h b/uwsgi.h index 17cd825c..eafea987 100644 --- a/uwsgi.h +++ b/uwsgi.h @@ -537,6 +537,7 @@ struct uwsgi_opt { #define LONG_ARGS_MULES 17158 #define LONG_ARGS_PROCNAME_PREFIX_SP 17159 #define LONG_ARGS_UMASK 17160 +#define LONG_ARGS_PAUSE 17161 #define UWSGI_OK 0 @@ -1728,6 +1729,7 @@ struct uwsgi_worker { int busy; int cheaped; + int suspended; int sig; uint8_t signum;