From 476d2d789b68991c899f5fc63da108f402ed20db Mon Sep 17 00:00:00 2001 From: "Kyle J. McKay" Date: Thu, 3 Dec 2015 11:20:38 -0800 Subject: [PATCH] server.c: support -i idle timeout option After of no activity the server will initiate a graceful shutdown. Defaults to off (0). Signed-off-by: Kyle J. McKay --- src/server.c | 49 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 10 deletions(-) diff --git a/src/server.c b/src/server.c index 6200c94c..9c9840f5 100644 --- a/src/server.c +++ b/src/server.c @@ -526,6 +526,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" \ @@ -548,6 +549,8 @@ int main (int argc, char **argv) { int num_childs = 0; int pid_fd = -1, fd; size_t i; + time_t idle_timeout = 0, server_activity = time(NULL); + int timed_out = 0; #ifdef HAVE_SIGACTION struct sigaction act; #endif @@ -583,7 +586,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) { @@ -601,6 +604,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_timeout = (time_t)timeout; + break; + } case 'p': print_config = 1; break; case 't': test_config = 1; break; case 'D': srv->srvconf.dont_daemonize = 1; break; @@ -1487,6 +1502,7 @@ int main (int argc, char **argv) { "polls:", n); } #endif + server_activity = time(NULL); fd_ndx = -1; do { fdevent_handler handler; @@ -1527,6 +1543,14 @@ int main (int argc, char **argv) { strerror(errno)); } + if (idle_timeout && time(NULL) - server_activity >= idle_timeout) { + log_error_write(srv, __FILE__, __LINE__, "sDs", "[note] idle timeout", (int)idle_timeout, + "s exceeded, graceful shutdown started"); + timed_out = 1; + graceful_shutdown = 1; + break; + } + for (ndx = 0; ndx < srv->joblist->used; ndx++) { connection *con = srv->joblist->ptr[ndx]; handler_t r; @@ -1549,7 +1573,7 @@ int main (int argc, char **argv) { } if (!buffer_string_is_empty(srv->srvconf.pid_file) && - 0 == graceful_shutdown && 0 <= pid_fd) { + (0 == graceful_shutdown || timed_out) && 0 <= pid_fd) { if (0 != ftruncate(pid_fd, 0)) { log_error_write(srv, __FILE__, __LINE__, "sbds", "ftruncate failed for:", @@ -1564,7 +1588,7 @@ int main (int argc, char **argv) { } if (!buffer_string_is_empty(srv->srvconf.pid_file) && buffer_string_is_empty(srv->srvconf.changeroot) && - 0 == graceful_shutdown) { + (0 == graceful_shutdown || timed_out)) { if (0 != unlink(srv->srvconf.pid_file->ptr)) { if (errno != EACCES && errno != EPERM) { log_error_write(srv, __FILE__, __LINE__, "sbds", @@ -1576,16 +1600,21 @@ int main (int argc, char **argv) { } } + if (timed_out) { + log_error_write(srv, __FILE__, __LINE__, "s", + "server stopped by 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); -- 2.4.10