Project

General

Profile

0006-server.c-support-i-secs-idle-timeout-option_patch.txt

gstrauss, 2016-03-18 02:43

 
1
diff --git a/src/server.c b/src/server.c
2
index 26ecbcc..fd07c85 100644
3
--- a/src/server.c
4
+++ b/src/server.c
5
@@ -530,6 +530,7 @@ static void show_help (void) {
6
 "usage:\n" \
7
 " -f <name>  filename of the config-file\n" \
8
 " -m <name>  module directory (default: "LIBRARY_DIR")\n" \
9
+" -i <secs>  graceful shutdown after <secs> of inactivity\n" \
10
 " -p         print the parsed config-file in internal form, and exit\n" \
11
 " -t         test the config-file, and exit\n" \
12
 " -D         don't go to background (default: go to background)\n" \
13
@@ -552,6 +553,7 @@ int main (int argc, char **argv) {
14
 	int num_childs = 0;
15
 	int pid_fd = -1, fd;
16
 	size_t i;
17
+	time_t idle_limit = 0, last_active_ts = time(NULL);
18
 #ifdef HAVE_SIGACTION
19
 	struct sigaction act;
20
 #endif
21
@@ -587,7 +589,7 @@ int main (int argc, char **argv) {
22
 #endif
23
 	srv->srvconf.dont_daemonize = 0;
24
 
25
-	while(-1 != (o = getopt(argc, argv, "f:m:hvVDpt"))) {
26
+	while(-1 != (o = getopt(argc, argv, "f:m:i:hvVDpt"))) {
27
 		switch(o) {
28
 		case 'f':
29
 			if (srv->config_storage) {
30
@@ -605,6 +607,18 @@ int main (int argc, char **argv) {
31
 		case 'm':
32
 			buffer_copy_string(srv->srvconf.modules_dir, optarg);
33
 			break;
34
+		case 'i': {
35
+			char *endptr;
36
+			long timeout = strtol(optarg, &endptr, 0);
37
+			if (!*optarg || *endptr || timeout < 0) {
38
+				log_error_write(srv, __FILE__, __LINE__, "ss",
39
+						"Invalid idle timeout value:", optarg);
40
+				server_free(srv);
41
+				return -1;
42
+			}
43
+			idle_limit = (time_t)timeout;
44
+			break;
45
+		}
46
 		case 'p': print_config = 1; break;
47
 		case 't': test_config = 1; break;
48
 		case 'D': srv->srvconf.dont_daemonize = 1; break;
49
@@ -1082,6 +1096,11 @@ int main (int argc, char **argv) {
50
 	num_childs = srv->srvconf.max_worker;
51
 	if (num_childs > 0) {
52
 		int child = 0;
53
+		if (idle_limit) {
54
+			idle_limit = 0;
55
+			log_error_write(srv, __FILE__, __LINE__, "s",
56
+					"server idle time limit disabled with server.max-worker (combination not supported).");
57
+		}
58
 		while (!child && !srv_shutdown && !graceful_shutdown) {
59
 			if (num_childs > 0) {
60
 				switch (fork()) {
61
@@ -1291,6 +1310,13 @@ int main (int argc, char **argv) {
62
 				/* trigger waitpid */
63
 				srv->cur_ts = min_ts;
64
 
65
+				/* check idle time limit, if enabled */
66
+				if (idle_limit && idle_limit < min_ts - last_active_ts && !graceful_shutdown) {
67
+					log_error_write(srv, __FILE__, __LINE__, "sDs", "[note] idle timeout", (int)idle_limit,
68
+							"s exceeded, initiating graceful shutdown");
69
+					graceful_shutdown = 2; /* value 2 indicates idle timeout */
70
+				}
71
+
72
 				/* cleanup stat-cache */
73
 				stat_cache_trigger_cleanup(srv);
74
 				/**
75
@@ -1493,6 +1519,7 @@ int main (int argc, char **argv) {
76
 						"polls:", n);
77
 			}
78
 #endif
79
+			last_active_ts = srv->cur_ts;
80
 			fd_ndx = -1;
81
 			do {
82
 				fdevent_handler handler;
83
@@ -1568,16 +1595,21 @@ int main (int argc, char **argv) {
84
 		}
85
 	}
86
 
87
+	if (2 == graceful_shutdown) { /* value 2 indicates idle timeout */
88
+		log_error_write(srv, __FILE__, __LINE__, "s",
89
+				"server stopped after idle timeout");
90
+	} else {
91
 #ifdef HAVE_SIGACTION
92
-	log_error_write(srv, __FILE__, __LINE__, "sdsd", 
93
-			"server stopped by UID =",
94
-			last_sigterm_info.si_uid,
95
-			"PID =",
96
-			last_sigterm_info.si_pid);
97
+		log_error_write(srv, __FILE__, __LINE__, "sdsd",
98
+				"server stopped by UID =",
99
+				last_sigterm_info.si_uid,
100
+				"PID =",
101
+				last_sigterm_info.si_pid);
102
 #else
103
-	log_error_write(srv, __FILE__, __LINE__, "s", 
104
-			"server stopped");
105
+		log_error_write(srv, __FILE__, __LINE__, "s",
106
+				"server stopped");
107
 #endif
108
+	}
109
 
110
 	/* clean-up */
111
 	log_error_close(srv);