diff --git a/src/server.c b/src/server.c index 26ecbcc..fd07c85 100644 --- a/src/server.c +++ b/src/server.c @@ -530,6 +530,7 @@ static void show_help (void) { "usage:\n" \ " -f filename of the config-file\n" \ " -m module directory (default: "LIBRARY_DIR")\n" \ +" -i graceful shutdown after of inactivity\n" \ " -p print the parsed config-file in internal form, and exit\n" \ " -t test the config-file, and exit\n" \ " -D don't go to background (default: go to background)\n" \ @@ -552,6 +553,7 @@ int main (int argc, char **argv) { int num_childs = 0; int pid_fd = -1, fd; size_t i; + time_t idle_limit = 0, last_active_ts = time(NULL); #ifdef HAVE_SIGACTION struct sigaction act; #endif @@ -587,7 +589,7 @@ int main (int argc, char **argv) { #endif srv->srvconf.dont_daemonize = 0; - while(-1 != (o = getopt(argc, argv, "f:m:hvVDpt"))) { + while(-1 != (o = getopt(argc, argv, "f:m:i:hvVDpt"))) { switch(o) { case 'f': if (srv->config_storage) { @@ -605,6 +607,18 @@ int main (int argc, char **argv) { case 'm': buffer_copy_string(srv->srvconf.modules_dir, optarg); break; + case 'i': { + char *endptr; + long timeout = strtol(optarg, &endptr, 0); + if (!*optarg || *endptr || timeout < 0) { + log_error_write(srv, __FILE__, __LINE__, "ss", + "Invalid idle timeout value:", optarg); + server_free(srv); + return -1; + } + idle_limit = (time_t)timeout; + break; + } case 'p': print_config = 1; break; case 't': test_config = 1; break; case 'D': srv->srvconf.dont_daemonize = 1; break; @@ -1082,6 +1096,11 @@ int main (int argc, char **argv) { num_childs = srv->srvconf.max_worker; if (num_childs > 0) { int child = 0; + if (idle_limit) { + idle_limit = 0; + log_error_write(srv, __FILE__, __LINE__, "s", + "server idle time limit disabled with server.max-worker (combination not supported)."); + } while (!child && !srv_shutdown && !graceful_shutdown) { if (num_childs > 0) { switch (fork()) { @@ -1291,6 +1310,13 @@ int main (int argc, char **argv) { /* trigger waitpid */ srv->cur_ts = min_ts; + /* check idle time limit, if enabled */ + if (idle_limit && idle_limit < min_ts - last_active_ts && !graceful_shutdown) { + log_error_write(srv, __FILE__, __LINE__, "sDs", "[note] idle timeout", (int)idle_limit, + "s exceeded, initiating graceful shutdown"); + graceful_shutdown = 2; /* value 2 indicates idle timeout */ + } + /* cleanup stat-cache */ stat_cache_trigger_cleanup(srv); /** @@ -1493,6 +1519,7 @@ int main (int argc, char **argv) { "polls:", n); } #endif + last_active_ts = srv->cur_ts; fd_ndx = -1; do { fdevent_handler handler; @@ -1568,16 +1595,21 @@ int main (int argc, char **argv) { } } + if (2 == graceful_shutdown) { /* value 2 indicates idle timeout */ + log_error_write(srv, __FILE__, __LINE__, "s", + "server stopped after idle timeout"); + } else { #ifdef HAVE_SIGACTION - log_error_write(srv, __FILE__, __LINE__, "sdsd", - "server stopped by UID =", - last_sigterm_info.si_uid, - "PID =", - last_sigterm_info.si_pid); + log_error_write(srv, __FILE__, __LINE__, "sdsd", + "server stopped by UID =", + last_sigterm_info.si_uid, + "PID =", + last_sigterm_info.si_pid); #else - log_error_write(srv, __FILE__, __LINE__, "s", - "server stopped"); + log_error_write(srv, __FILE__, __LINE__, "s", + "server stopped"); #endif + } /* clean-up */ log_error_close(srv);