176404edcSAsim Jamshed #ifdef MULTI_THREADED
276404edcSAsim Jamshed #ifndef _GNU_SOURCE
376404edcSAsim Jamshed #define _GNU_SOURCE
476404edcSAsim Jamshed #endif
576404edcSAsim Jamshed #include <pthread.h>
676404edcSAsim Jamshed #include <numa.h>
776404edcSAsim Jamshed #include <sched.h>
876404edcSAsim Jamshed #endif
976404edcSAsim Jamshed 
1076404edcSAsim Jamshed #include "server.h"
1176404edcSAsim Jamshed #include "buffer.h"
1276404edcSAsim Jamshed #include "network.h"
1376404edcSAsim Jamshed #include "log.h"
1476404edcSAsim Jamshed #include "keyvalue.h"
1576404edcSAsim Jamshed #include "response.h"
1676404edcSAsim Jamshed #include "request.h"
1776404edcSAsim Jamshed #include "chunk.h"
1876404edcSAsim Jamshed #include "http_chunk.h"
1976404edcSAsim Jamshed #include "fdevent.h"
2076404edcSAsim Jamshed #include "connections.h"
2176404edcSAsim Jamshed #include "stat_cache.h"
2276404edcSAsim Jamshed #include "plugin.h"
2376404edcSAsim Jamshed #include "joblist.h"
2476404edcSAsim Jamshed #include "network_backends.h"
2576404edcSAsim Jamshed #include "version.h"
2676404edcSAsim Jamshed 
2776404edcSAsim Jamshed #include <sys/types.h>
2876404edcSAsim Jamshed #include <sys/time.h>
2976404edcSAsim Jamshed #include <sys/stat.h>
3076404edcSAsim Jamshed 
3176404edcSAsim Jamshed #include <string.h>
3276404edcSAsim Jamshed #include <errno.h>
3376404edcSAsim Jamshed #include <fcntl.h>
3476404edcSAsim Jamshed #include <unistd.h>
3576404edcSAsim Jamshed #include <stdlib.h>
3676404edcSAsim Jamshed #include <time.h>
3776404edcSAsim Jamshed #include <signal.h>
3876404edcSAsim Jamshed #include <assert.h>
3976404edcSAsim Jamshed #include <locale.h>
4076404edcSAsim Jamshed 
4176404edcSAsim Jamshed #include <stdio.h>
4276404edcSAsim Jamshed 
4376404edcSAsim Jamshed #ifdef HAVE_GETOPT_H
4476404edcSAsim Jamshed # include <getopt.h>
4576404edcSAsim Jamshed #endif
4676404edcSAsim Jamshed 
4776404edcSAsim Jamshed #ifdef HAVE_VALGRIND_VALGRIND_H
4876404edcSAsim Jamshed # include <valgrind/valgrind.h>
4976404edcSAsim Jamshed #endif
5076404edcSAsim Jamshed 
5176404edcSAsim Jamshed #ifdef HAVE_SYS_WAIT_H
5276404edcSAsim Jamshed # include <sys/wait.h>
5376404edcSAsim Jamshed #endif
5476404edcSAsim Jamshed 
5576404edcSAsim Jamshed #ifdef HAVE_PWD_H
5676404edcSAsim Jamshed # include <grp.h>
5776404edcSAsim Jamshed # include <pwd.h>
5876404edcSAsim Jamshed #endif
5976404edcSAsim Jamshed 
6076404edcSAsim Jamshed #ifdef HAVE_SYS_RESOURCE_H
6176404edcSAsim Jamshed # include <sys/resource.h>
6276404edcSAsim Jamshed #endif
6376404edcSAsim Jamshed 
6476404edcSAsim Jamshed #ifdef HAVE_SYS_PRCTL_H
6576404edcSAsim Jamshed # include <sys/prctl.h>
6676404edcSAsim Jamshed #endif
6776404edcSAsim Jamshed 
6876404edcSAsim Jamshed #ifdef USE_OPENSSL
6976404edcSAsim Jamshed # include <openssl/err.h>
7076404edcSAsim Jamshed #endif
7176404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
7276404edcSAsim Jamshed #ifndef __sgi
7376404edcSAsim Jamshed /* IRIX doesn't like the alarm based time() optimization */
7476404edcSAsim Jamshed /* #define USE_ALARM */
7576404edcSAsim Jamshed #endif
7676404edcSAsim Jamshed 
7776404edcSAsim Jamshed #ifdef HAVE_GETUID
7876404edcSAsim Jamshed # ifndef HAVE_ISSETUGID
7976404edcSAsim Jamshed 
8076404edcSAsim Jamshed static int
l_issetugid(void)8176404edcSAsim Jamshed l_issetugid(void) {
8276404edcSAsim Jamshed 	return (geteuid() != getuid() || getegid() != getgid());
8376404edcSAsim Jamshed }
8476404edcSAsim Jamshed 
8576404edcSAsim Jamshed #  define issetugid l_issetugid
8676404edcSAsim Jamshed # endif
8776404edcSAsim Jamshed #endif
8876404edcSAsim Jamshed 
8976404edcSAsim Jamshed static volatile sig_atomic_t srv_shutdown = 0;
9076404edcSAsim Jamshed static volatile sig_atomic_t graceful_shutdown = 0;
9176404edcSAsim Jamshed static volatile sig_atomic_t handle_sig_alarm = 1;
9276404edcSAsim Jamshed static volatile sig_atomic_t handle_sig_hup = 0;
9376404edcSAsim Jamshed static volatile sig_atomic_t forwarded_sig_hup = 0;
9476404edcSAsim Jamshed 
9576404edcSAsim Jamshed #if defined(HAVE_SIGACTION) && defined(SA_SIGINFO)
9676404edcSAsim Jamshed static volatile siginfo_t last_sigterm_info;
9776404edcSAsim Jamshed static volatile siginfo_t last_sighup_info;
9876404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
9976404edcSAsim Jamshed static void
sigaction_handler(int sig,siginfo_t * si,void * context)10076404edcSAsim Jamshed sigaction_handler(int sig, siginfo_t *si, void *context) {
10176404edcSAsim Jamshed 	static siginfo_t empty_siginfo;
10276404edcSAsim Jamshed 	UNUSED(context);
10376404edcSAsim Jamshed 
10476404edcSAsim Jamshed 	if (!si) si = &empty_siginfo;
10576404edcSAsim Jamshed 
10676404edcSAsim Jamshed 	switch (sig) {
10776404edcSAsim Jamshed 	case SIGTERM:
10876404edcSAsim Jamshed 		srv_shutdown = 1;
10976404edcSAsim Jamshed 		last_sigterm_info = *si;
11076404edcSAsim Jamshed 		break;
11176404edcSAsim Jamshed 	case SIGINT:
11276404edcSAsim Jamshed 		if (graceful_shutdown) {
11376404edcSAsim Jamshed 			srv_shutdown = 1;
11476404edcSAsim Jamshed 		} else {
11576404edcSAsim Jamshed 			graceful_shutdown = 1;
11676404edcSAsim Jamshed 		}
11776404edcSAsim Jamshed 		last_sigterm_info = *si;
11876404edcSAsim Jamshed 
11976404edcSAsim Jamshed 		break;
12076404edcSAsim Jamshed 	case SIGALRM:
12176404edcSAsim Jamshed 		handle_sig_alarm = 1;
12276404edcSAsim Jamshed 		break;
12376404edcSAsim Jamshed 	case SIGHUP:
12476404edcSAsim Jamshed 		/**
12576404edcSAsim Jamshed 		 * we send the SIGHUP to all procs in the process-group
12676404edcSAsim Jamshed 		 * this includes ourself
12776404edcSAsim Jamshed 		 *
12876404edcSAsim Jamshed 		 * make sure we only send it once and don't create a
12976404edcSAsim Jamshed 		 * infinite loop
13076404edcSAsim Jamshed 		 */
13176404edcSAsim Jamshed 		if (!forwarded_sig_hup) {
13276404edcSAsim Jamshed 			handle_sig_hup = 1;
13376404edcSAsim Jamshed 			last_sighup_info = *si;
13476404edcSAsim Jamshed 		} else {
13576404edcSAsim Jamshed 			forwarded_sig_hup = 0;
13676404edcSAsim Jamshed 		}
13776404edcSAsim Jamshed 		break;
13876404edcSAsim Jamshed 	case SIGCHLD:
13976404edcSAsim Jamshed 		break;
14076404edcSAsim Jamshed 	}
14176404edcSAsim Jamshed }
14276404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
14376404edcSAsim Jamshed #elif defined(HAVE_SIGNAL) || defined(HAVE_SIGACTION)
14476404edcSAsim Jamshed static void
signal_handler(int sig)14576404edcSAsim Jamshed signal_handler(int sig) {
14676404edcSAsim Jamshed 	switch (sig) {
14776404edcSAsim Jamshed 	case SIGTERM: srv_shutdown = 1; break;
14876404edcSAsim Jamshed 	case SIGINT:
14976404edcSAsim Jamshed 	     if (graceful_shutdown) srv_shutdown = 1;
15076404edcSAsim Jamshed 	     else graceful_shutdown = 1;
15176404edcSAsim Jamshed 	     break;
15276404edcSAsim Jamshed 	case SIGALRM: handle_sig_alarm = 1; break;
15376404edcSAsim Jamshed 	case SIGHUP:  handle_sig_hup = 1; break;
15476404edcSAsim Jamshed 	case SIGCHLD:  break;
15576404edcSAsim Jamshed 	}
15676404edcSAsim Jamshed }
15776404edcSAsim Jamshed #endif
15876404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
15976404edcSAsim Jamshed #ifdef MULTI_THREADED
16076404edcSAsim Jamshed /* TODO - signal handling logic will be revised in future revisions */
16176404edcSAsim Jamshed static void
signal_handler(int sig)16276404edcSAsim Jamshed signal_handler(int sig) {
16376404edcSAsim Jamshed 	switch (sig) {
16476404edcSAsim Jamshed 	case SIGTERM: srv_shutdown = 1; break;
16576404edcSAsim Jamshed 	case SIGINT:
16676404edcSAsim Jamshed 		if (graceful_shutdown) srv_shutdown = 1;
16776404edcSAsim Jamshed 		else graceful_shutdown = 1;
16876404edcSAsim Jamshed 
16976404edcSAsim Jamshed 		break;
17076404edcSAsim Jamshed 	case SIGALRM: handle_sig_alarm = 1; break;
17176404edcSAsim Jamshed 	case SIGHUP:  handle_sig_hup = 1; break;
17276404edcSAsim Jamshed 	case SIGCHLD:  break;
17376404edcSAsim Jamshed 	}
17476404edcSAsim Jamshed #ifdef HAVE_LIBDPDK
17576404edcSAsim Jamshed         exit(EXIT_SUCCESS);
17676404edcSAsim Jamshed #endif
17776404edcSAsim Jamshed }
17876404edcSAsim Jamshed #endif
17976404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
18076404edcSAsim Jamshed #ifdef HAVE_FORK
18176404edcSAsim Jamshed static void
daemonize(void)18276404edcSAsim Jamshed daemonize(void) {
18376404edcSAsim Jamshed #ifdef SIGTTOU
18476404edcSAsim Jamshed 	signal(SIGTTOU, SIG_IGN);
18576404edcSAsim Jamshed #endif
18676404edcSAsim Jamshed #ifdef SIGTTIN
18776404edcSAsim Jamshed 	signal(SIGTTIN, SIG_IGN);
18876404edcSAsim Jamshed #endif
18976404edcSAsim Jamshed #ifdef SIGTSTP
19076404edcSAsim Jamshed 	signal(SIGTSTP, SIG_IGN);
19176404edcSAsim Jamshed #endif
19276404edcSAsim Jamshed 	if (0 != fork()) exit(EXIT_SUCCESS);
19376404edcSAsim Jamshed 
19476404edcSAsim Jamshed 	if (-1 == setsid()) exit(EXIT_SUCCESS);
19576404edcSAsim Jamshed 
19676404edcSAsim Jamshed 	signal(SIGHUP, SIG_IGN);
19776404edcSAsim Jamshed 
19876404edcSAsim Jamshed 	if (0 != fork()) exit(EXIT_SUCCESS);
19976404edcSAsim Jamshed 
20076404edcSAsim Jamshed 	if (0 != chdir("/")) exit(EXIT_SUCCESS);
20176404edcSAsim Jamshed }
20276404edcSAsim Jamshed #endif
20376404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
20476404edcSAsim Jamshed static server *
server_init(void)20576404edcSAsim Jamshed server_init(void) {
20676404edcSAsim Jamshed 	int i;
20776404edcSAsim Jamshed 	FILE *frandom = NULL;
20876404edcSAsim Jamshed 
20976404edcSAsim Jamshed 	server *srv = calloc(1, sizeof(*srv));
21076404edcSAsim Jamshed 	assert(srv);
21176404edcSAsim Jamshed #define CLEAN(x)				\
21276404edcSAsim Jamshed 	srv->x = buffer_init();
21376404edcSAsim Jamshed 
21476404edcSAsim Jamshed 	CLEAN(response_header);
21576404edcSAsim Jamshed 	CLEAN(parse_full_path);
21676404edcSAsim Jamshed 	CLEAN(ts_debug_str);
21776404edcSAsim Jamshed 	CLEAN(ts_date_str);
21876404edcSAsim Jamshed 	CLEAN(errorlog_buf);
21976404edcSAsim Jamshed 	CLEAN(response_range);
22076404edcSAsim Jamshed 	CLEAN(tmp_buf);
22176404edcSAsim Jamshed 	srv->empty_string = buffer_init_string("");
22276404edcSAsim Jamshed 	CLEAN(cond_check_buf);
22376404edcSAsim Jamshed 
22476404edcSAsim Jamshed 	CLEAN(srvconf.errorlog_file);
22576404edcSAsim Jamshed 	CLEAN(srvconf.breakagelog_file);
22676404edcSAsim Jamshed 	CLEAN(srvconf.groupname);
22776404edcSAsim Jamshed 	CLEAN(srvconf.username);
22876404edcSAsim Jamshed 	CLEAN(srvconf.changeroot);
22976404edcSAsim Jamshed 	CLEAN(srvconf.bindhost);
23076404edcSAsim Jamshed 	CLEAN(srvconf.event_handler);
23176404edcSAsim Jamshed 	CLEAN(srvconf.pid_file);
23276404edcSAsim Jamshed 
23376404edcSAsim Jamshed 	CLEAN(tmp_chunk_len);
23476404edcSAsim Jamshed #undef CLEAN
23576404edcSAsim Jamshed 
23676404edcSAsim Jamshed #define CLEAN(x) \
23776404edcSAsim Jamshed 	srv->x = array_init();
23876404edcSAsim Jamshed 
23976404edcSAsim Jamshed 	CLEAN(config_context);
24076404edcSAsim Jamshed 	CLEAN(config_touched);
24176404edcSAsim Jamshed 	CLEAN(status);
24276404edcSAsim Jamshed #undef CLEAN
24376404edcSAsim Jamshed 
24476404edcSAsim Jamshed 	for (i = 0; i < FILE_CACHE_MAX; i++) {
24576404edcSAsim Jamshed 		srv->mtime_cache[i].mtime = (time_t)-1;
24676404edcSAsim Jamshed 		srv->mtime_cache[i].str = buffer_init();
24776404edcSAsim Jamshed 	}
24876404edcSAsim Jamshed 
24976404edcSAsim Jamshed 	if ((NULL != (frandom = fopen("/dev/urandom", "rb")) || NULL != (frandom = fopen("/dev/random", "rb")))
25076404edcSAsim Jamshed 	            && 1 == fread(srv->entropy, sizeof(srv->entropy), 1, frandom)) {
25176404edcSAsim Jamshed 		unsigned int e;
25276404edcSAsim Jamshed 		memcpy(&e, srv->entropy, sizeof(e) < sizeof(srv->entropy) ? sizeof(e) : sizeof(srv->entropy));
25376404edcSAsim Jamshed 		srand(e);
25476404edcSAsim Jamshed 		srv->is_real_entropy = 1;
25576404edcSAsim Jamshed 	} else {
25676404edcSAsim Jamshed 		unsigned int j;
25776404edcSAsim Jamshed 		srand(time(NULL) ^ getpid());
25876404edcSAsim Jamshed 		srv->is_real_entropy = 0;
25976404edcSAsim Jamshed 		for (j = 0; j < sizeof(srv->entropy); j++)
26076404edcSAsim Jamshed 			srv->entropy[j] = rand();
26176404edcSAsim Jamshed 	}
26276404edcSAsim Jamshed 	if (frandom) fclose(frandom);
26376404edcSAsim Jamshed 
26476404edcSAsim Jamshed 	srv->cur_ts = time(NULL);
26576404edcSAsim Jamshed 	srv->startup_ts = srv->cur_ts;
26676404edcSAsim Jamshed 
26776404edcSAsim Jamshed 	srv->conns = calloc(1, sizeof(*srv->conns));
26876404edcSAsim Jamshed 	assert(srv->conns);
26976404edcSAsim Jamshed 
27076404edcSAsim Jamshed 	srv->joblist = calloc(1, sizeof(*srv->joblist));
27176404edcSAsim Jamshed 	assert(srv->joblist);
27276404edcSAsim Jamshed 
27376404edcSAsim Jamshed 	srv->fdwaitqueue = calloc(1, sizeof(*srv->fdwaitqueue));
27476404edcSAsim Jamshed 	assert(srv->fdwaitqueue);
27576404edcSAsim Jamshed 
27676404edcSAsim Jamshed 	srv->srvconf.modules = array_init();
27776404edcSAsim Jamshed 	srv->srvconf.modules_dir = buffer_init_string(LIBRARY_DIR);
27876404edcSAsim Jamshed 	srv->srvconf.network_backend = buffer_init();
27976404edcSAsim Jamshed 	srv->srvconf.upload_tempdirs = array_init();
28076404edcSAsim Jamshed 	srv->srvconf.reject_expect_100_with_417 = 1;
28176404edcSAsim Jamshed 
28276404edcSAsim Jamshed 	/* use syslog */
28376404edcSAsim Jamshed 	srv->errorlog_fd = STDERR_FILENO;
28476404edcSAsim Jamshed 	srv->errorlog_mode = ERRORLOG_FD;
28576404edcSAsim Jamshed 
28676404edcSAsim Jamshed 	srv->split_vals = array_init();
28776404edcSAsim Jamshed 
28876404edcSAsim Jamshed 	return srv;
28976404edcSAsim Jamshed }
29076404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
29176404edcSAsim Jamshed static void
server_free(server * srv)29276404edcSAsim Jamshed server_free(server *srv) {
29376404edcSAsim Jamshed 	size_t i;
29476404edcSAsim Jamshed 
29576404edcSAsim Jamshed 	for (i = 0; i < FILE_CACHE_MAX; i++) {
29676404edcSAsim Jamshed 		buffer_free(srv->mtime_cache[i].str);
29776404edcSAsim Jamshed 	}
29876404edcSAsim Jamshed 
29976404edcSAsim Jamshed #define CLEAN(x) \
30076404edcSAsim Jamshed 	buffer_free(srv->x);
30176404edcSAsim Jamshed 
30276404edcSAsim Jamshed 	CLEAN(response_header);
30376404edcSAsim Jamshed 	CLEAN(parse_full_path);
30476404edcSAsim Jamshed 	CLEAN(ts_debug_str);
30576404edcSAsim Jamshed 	CLEAN(ts_date_str);
30676404edcSAsim Jamshed 	CLEAN(errorlog_buf);
30776404edcSAsim Jamshed 	CLEAN(response_range);
30876404edcSAsim Jamshed 	CLEAN(tmp_buf);
30976404edcSAsim Jamshed 	CLEAN(empty_string);
31076404edcSAsim Jamshed 	CLEAN(cond_check_buf);
31176404edcSAsim Jamshed 
31276404edcSAsim Jamshed 	CLEAN(srvconf.errorlog_file);
31376404edcSAsim Jamshed 	CLEAN(srvconf.breakagelog_file);
31476404edcSAsim Jamshed 	CLEAN(srvconf.groupname);
31576404edcSAsim Jamshed 	CLEAN(srvconf.username);
31676404edcSAsim Jamshed 	CLEAN(srvconf.changeroot);
31776404edcSAsim Jamshed 	CLEAN(srvconf.bindhost);
31876404edcSAsim Jamshed 	CLEAN(srvconf.event_handler);
31976404edcSAsim Jamshed 	CLEAN(srvconf.pid_file);
32076404edcSAsim Jamshed 	CLEAN(srvconf.modules_dir);
32176404edcSAsim Jamshed 	CLEAN(srvconf.network_backend);
32276404edcSAsim Jamshed 
32376404edcSAsim Jamshed 	CLEAN(tmp_chunk_len);
32476404edcSAsim Jamshed #undef CLEAN
32576404edcSAsim Jamshed 
32676404edcSAsim Jamshed #if 0
32776404edcSAsim Jamshed 	fdevent_unregister(srv->ev, srv->fd);
32876404edcSAsim Jamshed #endif
32976404edcSAsim Jamshed 	fdevent_free(srv->ev);
33076404edcSAsim Jamshed 
33176404edcSAsim Jamshed 	free(srv->conns);
33276404edcSAsim Jamshed 
33376404edcSAsim Jamshed 	if (srv->config_storage) {
33476404edcSAsim Jamshed 		for (i = 0; i < srv->config_context->used; i++) {
33576404edcSAsim Jamshed 			specific_config *s = srv->config_storage[i];
33676404edcSAsim Jamshed 
33776404edcSAsim Jamshed 			if (!s) continue;
33876404edcSAsim Jamshed 
33976404edcSAsim Jamshed 			buffer_free(s->document_root);
34076404edcSAsim Jamshed 			buffer_free(s->server_name);
34176404edcSAsim Jamshed 			buffer_free(s->server_tag);
34276404edcSAsim Jamshed 			buffer_free(s->ssl_pemfile);
34376404edcSAsim Jamshed 			buffer_free(s->ssl_ca_file);
34476404edcSAsim Jamshed 			buffer_free(s->ssl_cipher_list);
34576404edcSAsim Jamshed 			buffer_free(s->ssl_dh_file);
34676404edcSAsim Jamshed 			buffer_free(s->ssl_ec_curve);
34776404edcSAsim Jamshed 			buffer_free(s->error_handler);
34876404edcSAsim Jamshed 			buffer_free(s->errorfile_prefix);
34976404edcSAsim Jamshed 			array_free(s->mimetypes);
35076404edcSAsim Jamshed 			buffer_free(s->ssl_verifyclient_username);
35176404edcSAsim Jamshed #ifdef USE_OPENSSL
35276404edcSAsim Jamshed 			SSL_CTX_free(s->ssl_ctx);
35376404edcSAsim Jamshed #endif
35476404edcSAsim Jamshed 			free(s);
35576404edcSAsim Jamshed 		}
35676404edcSAsim Jamshed 		free(srv->config_storage);
35776404edcSAsim Jamshed 		srv->config_storage = NULL;
35876404edcSAsim Jamshed 	}
35976404edcSAsim Jamshed 
36076404edcSAsim Jamshed #define CLEAN(x) \
36176404edcSAsim Jamshed 	array_free(srv->x);
36276404edcSAsim Jamshed 
36376404edcSAsim Jamshed 	CLEAN(config_context);
36476404edcSAsim Jamshed 	CLEAN(config_touched);
36576404edcSAsim Jamshed 	CLEAN(status);
36676404edcSAsim Jamshed 	CLEAN(srvconf.upload_tempdirs);
36776404edcSAsim Jamshed #undef CLEAN
36876404edcSAsim Jamshed 
36976404edcSAsim Jamshed 	joblist_free(srv, srv->joblist);
37076404edcSAsim Jamshed 	fdwaitqueue_free(srv, srv->fdwaitqueue);
37176404edcSAsim Jamshed 
37276404edcSAsim Jamshed 	if (srv->stat_cache) {
37376404edcSAsim Jamshed 		stat_cache_free(srv->stat_cache);
37476404edcSAsim Jamshed 	}
37576404edcSAsim Jamshed 
37676404edcSAsim Jamshed 	array_free(srv->srvconf.modules);
37776404edcSAsim Jamshed 	array_free(srv->split_vals);
37876404edcSAsim Jamshed 
37976404edcSAsim Jamshed #ifdef USE_OPENSSL
38076404edcSAsim Jamshed 	if (srv->ssl_is_init) {
38176404edcSAsim Jamshed 		CRYPTO_cleanup_all_ex_data();
38276404edcSAsim Jamshed 		ERR_free_strings();
38376404edcSAsim Jamshed 		ERR_remove_state(0);
38476404edcSAsim Jamshed 		EVP_cleanup();
38576404edcSAsim Jamshed 	}
38676404edcSAsim Jamshed #endif
38776404edcSAsim Jamshed 
38876404edcSAsim Jamshed 	free(srv);
38976404edcSAsim Jamshed }
39076404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
39176404edcSAsim Jamshed static inline void
load_plugins(server * srv)39276404edcSAsim Jamshed load_plugins(server *srv)
39376404edcSAsim Jamshed {
39476404edcSAsim Jamshed 	if (HANDLER_GO_ON != plugins_call_init(srv)) {
39576404edcSAsim Jamshed 		log_error_write(srv, __FILE__, __LINE__, "s",
39676404edcSAsim Jamshed 				"Initialization of plugins failed. Going down.");
39776404edcSAsim Jamshed 		exit(EXIT_FAILURE);
39876404edcSAsim Jamshed 	}
39976404edcSAsim Jamshed 
40076404edcSAsim Jamshed }
40176404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
40276404edcSAsim Jamshed static inline void
set_max_conns(server * srv,int restrict_limit)40376404edcSAsim Jamshed set_max_conns(server *srv, int restrict_limit)
40476404edcSAsim Jamshed {
40576404edcSAsim Jamshed 	if (restrict_limit) {
40676404edcSAsim Jamshed 		if (srv->srvconf.max_conns > srv->max_fds/2) {
40776404edcSAsim Jamshed 			/* we can't have more connections than max-fds/2 */
40876404edcSAsim Jamshed 			log_error_write(srv, __FILE__, __LINE__, "sdd",
40976404edcSAsim Jamshed 					"can't have more connections than fds/2: ",
41076404edcSAsim Jamshed 					srv->srvconf.max_conns, srv->max_fds);
41176404edcSAsim Jamshed 			srv->max_conns = srv->max_fds/2;
41276404edcSAsim Jamshed 		} else if (srv->srvconf.max_conns) {
41376404edcSAsim Jamshed 			/* otherwise respect the wishes of the user */
41476404edcSAsim Jamshed 			srv->max_conns = srv->srvconf.max_conns;
41576404edcSAsim Jamshed 		} else {
41676404edcSAsim Jamshed 			/* or use the default: we really don't want to hit max-fds */
41776404edcSAsim Jamshed 			srv->max_conns = srv->max_fds/3;
41876404edcSAsim Jamshed 		}
41976404edcSAsim Jamshed 	} else {
42076404edcSAsim Jamshed 		srv->max_conns = srv->srvconf.max_conns;
42176404edcSAsim Jamshed 	}
42276404edcSAsim Jamshed }
42376404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
42476404edcSAsim Jamshed static inline void
initialize_fd_framework(server * srv)42576404edcSAsim Jamshed initialize_fd_framework(server *srv)
42676404edcSAsim Jamshed {
42776404edcSAsim Jamshed 	size_t i;
42876404edcSAsim Jamshed 
42976404edcSAsim Jamshed 	/* the 2nd arg of fdevent_init in case of libmtcp is ignored */
43076404edcSAsim Jamshed 	if (NULL == (srv->ev = fdevent_init(srv, srv->max_fds + 1, srv->event_handler))) {
43176404edcSAsim Jamshed 		log_error_write(srv, __FILE__, __LINE__,
43276404edcSAsim Jamshed 				"s", "fdevent_init failed");
43376404edcSAsim Jamshed 		exit(EXIT_FAILURE);
43476404edcSAsim Jamshed 	}
43576404edcSAsim Jamshed 
43676404edcSAsim Jamshed 	/*
43776404edcSAsim Jamshed 	 * kqueue() is called here, select resets its internals,
43876404edcSAsim Jamshed 	 * all server sockets get their handlers
43976404edcSAsim Jamshed 	 *
44076404edcSAsim Jamshed 	 * */
44176404edcSAsim Jamshed 	if (0 != network_register_fdevents(srv)) {
44276404edcSAsim Jamshed 		exit(EXIT_FAILURE);
44376404edcSAsim Jamshed 	}
44476404edcSAsim Jamshed 
44576404edcSAsim Jamshed 	/* might fail if user is using fam (not gamin) and famd isn't running */
44676404edcSAsim Jamshed 	if (NULL == (srv->stat_cache = stat_cache_init())) {
44776404edcSAsim Jamshed 		log_error_write(srv, __FILE__, __LINE__, "s",
44876404edcSAsim Jamshed 			"stat-cache could not be setup, dieing.");
44976404edcSAsim Jamshed 		exit(EXIT_FAILURE);
45076404edcSAsim Jamshed 	}
45176404edcSAsim Jamshed 
45276404edcSAsim Jamshed #ifdef HAVE_FAM_H
45376404edcSAsim Jamshed i hope this does not work
45476404edcSAsim Jamshed 	/* setup FAM */
45576404edcSAsim Jamshed 	if (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_FAM) {
45676404edcSAsim Jamshed 		if (0 != FAMOpen2(srv->stat_cache->fam, "lighttpd")) {
45776404edcSAsim Jamshed 			log_error_write(srv, __FILE__, __LINE__, "s",
45876404edcSAsim Jamshed 					 "could not open a fam connection, dieing.");
45976404edcSAsim Jamshed 			exit(EXIT_FAILURE);
46076404edcSAsim Jamshed 		}
46176404edcSAsim Jamshed #ifdef HAVE_FAMNOEXISTS
46276404edcSAsim Jamshed 		FAMNoExists(srv->stat_cache->fam);
46376404edcSAsim Jamshed #endif
46476404edcSAsim Jamshed 
46576404edcSAsim Jamshed 		srv->stat_cache->fam_fcce_ndx = -1;
46676404edcSAsim Jamshed 		fdevent_register(srv->ev, FAMCONNECTION_GETFD(srv->stat_cache->fam), stat_cache_handle_fdevent, NULL);
46776404edcSAsim Jamshed 		fdevent_event_set(srv->ev, &(srv->stat_cache->fam_fcce_ndx), FAMCONNECTION_GETFD(srv->stat_cache->fam), FDEVENT_IN);
46876404edcSAsim Jamshed 	}
46976404edcSAsim Jamshed #endif
47076404edcSAsim Jamshed 
47176404edcSAsim Jamshed 
47276404edcSAsim Jamshed 	/* get the current number of FDs */
47376404edcSAsim Jamshed 	srv->cur_fds = open("/dev/null", O_RDONLY);
47476404edcSAsim Jamshed 	close(srv->cur_fds);
47576404edcSAsim Jamshed 
47676404edcSAsim Jamshed 	for (i = 0; i < srv->srv_sockets.used; i++) {
47776404edcSAsim Jamshed 		server_socket *srv_socket = srv->srv_sockets.ptr[i];
47876404edcSAsim Jamshed 		if (-1 == fdevent_fcntl_set(srv->ev, srv_socket->fd)) {
47976404edcSAsim Jamshed 			log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed:", strerror(errno));
48076404edcSAsim Jamshed 			exit(EXIT_FAILURE);
48176404edcSAsim Jamshed 		}
48276404edcSAsim Jamshed 	}
48376404edcSAsim Jamshed }
48476404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
48576404edcSAsim Jamshed #ifdef MULTI_THREADED
48676404edcSAsim Jamshed #ifdef USE_MTCP
48776404edcSAsim Jamshed static inline void
set_listen_backlog(server * srv)48876404edcSAsim Jamshed set_listen_backlog(server *srv)
48976404edcSAsim Jamshed {
49076404edcSAsim Jamshed 	fprintf(stderr, "Applying listen_backlog: %d\n", srv->srvconf.listen_backlog);
49176404edcSAsim Jamshed 	srv->listen_backlog = srv->srvconf.listen_backlog;
49276404edcSAsim Jamshed }
49376404edcSAsim Jamshed #endif
49476404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
49576404edcSAsim Jamshed int
core_affinitize(int cpu)49676404edcSAsim Jamshed core_affinitize(int cpu)
49776404edcSAsim Jamshed {
49876404edcSAsim Jamshed 	cpu_set_t *cmask;
49976404edcSAsim Jamshed 	struct bitmask *bmask;
50076404edcSAsim Jamshed 	size_t n;
50176404edcSAsim Jamshed 	int ret;
50276404edcSAsim Jamshed 
50376404edcSAsim Jamshed 	n = sysconf(_SC_NPROCESSORS_ONLN);
50476404edcSAsim Jamshed 
50576404edcSAsim Jamshed 	if (cpu < 0 || cpu >= (int) n) {
50676404edcSAsim Jamshed 		errno = -EINVAL;
50776404edcSAsim Jamshed 		return -1;
50876404edcSAsim Jamshed 	}
50976404edcSAsim Jamshed 
51076404edcSAsim Jamshed 	cmask = CPU_ALLOC(n);
51176404edcSAsim Jamshed 	if (cmask == NULL)
51276404edcSAsim Jamshed 		return -1;
51376404edcSAsim Jamshed 
51476404edcSAsim Jamshed 	CPU_ZERO_S(n, cmask);
51576404edcSAsim Jamshed 	CPU_SET_S(cpu, n, cmask);
51676404edcSAsim Jamshed 
51776404edcSAsim Jamshed 	ret = sched_setaffinity(0, n, cmask);
51876404edcSAsim Jamshed 
51976404edcSAsim Jamshed 	CPU_FREE(cmask);
52076404edcSAsim Jamshed 
52176404edcSAsim Jamshed 	if (numa_max_node() == 0)
52276404edcSAsim Jamshed 		return ret;
52376404edcSAsim Jamshed 
52476404edcSAsim Jamshed 	bmask = numa_bitmask_alloc(16);
52576404edcSAsim Jamshed 	assert(bmask);
52676404edcSAsim Jamshed 
52776404edcSAsim Jamshed 	numa_bitmask_setbit(bmask, cpu % 2);
52876404edcSAsim Jamshed 	numa_set_membind(bmask);
52976404edcSAsim Jamshed 	numa_bitmask_free(bmask);
53076404edcSAsim Jamshed 
53176404edcSAsim Jamshed 	return ret;
53276404edcSAsim Jamshed }
53376404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
53476404edcSAsim Jamshed static int
get_num_cpus(const char * strnum)53576404edcSAsim Jamshed get_num_cpus(const char *strnum)
53676404edcSAsim Jamshed {
53776404edcSAsim Jamshed 	return strtol(strnum, (char **) NULL, 10);
53876404edcSAsim Jamshed }
53976404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
54076404edcSAsim Jamshed static void
init_server_states(server *** srv_states,int cpus,server * first_entry,const char * conf_file)54176404edcSAsim Jamshed init_server_states(server ***srv_states, int cpus,
54276404edcSAsim Jamshed 		   server *first_entry, const char *conf_file)
54376404edcSAsim Jamshed {
54476404edcSAsim Jamshed 	int i;
54576404edcSAsim Jamshed 
54676404edcSAsim Jamshed 	/* initialize the array */
54776404edcSAsim Jamshed 	*srv_states = (server **)calloc(cpus, sizeof(server *));
54876404edcSAsim Jamshed 	if (NULL == *srv_states) {
54976404edcSAsim Jamshed 		fprintf(stderr, "%s: %d(%s) - Can't allocate memory for srv_states\n",
55076404edcSAsim Jamshed 			__FUNCTION__, __LINE__, __FILE__);
55176404edcSAsim Jamshed 		exit(EXIT_FAILURE);
55276404edcSAsim Jamshed 	}
55376404edcSAsim Jamshed 	/* put the first entry on index 0 */
55476404edcSAsim Jamshed 	(*srv_states)[0] = first_entry;
55576404edcSAsim Jamshed #if !(defined USE_MTCP || defined REUSEPORT)
55676404edcSAsim Jamshed 	//#ifndef USE_MTCP
55776404edcSAsim Jamshed 	((*srv_states)[0])->first_entry = first_entry;
55876404edcSAsim Jamshed #else
55976404edcSAsim Jamshed #ifdef USE_MTCP
56076404edcSAsim Jamshed 	/* set listen-backlog */
56176404edcSAsim Jamshed 	set_listen_backlog(first_entry);
56276404edcSAsim Jamshed #endif
56376404edcSAsim Jamshed #endif
56476404edcSAsim Jamshed 
56576404edcSAsim Jamshed 	/* now do the same for all remaining reserved cpus */
56676404edcSAsim Jamshed 	for (i = 1; i < cpus; i++) {
56776404edcSAsim Jamshed 		/* initialize it */
56876404edcSAsim Jamshed 		if (NULL == ((*srv_states)[i] = server_init())) {
56976404edcSAsim Jamshed 			fprintf(stderr, "%s: %d(%s) - Can't allocate memory for %dth srv_state entry\n",
57076404edcSAsim Jamshed 				__FUNCTION__, __LINE__, __FILE__, i);
57176404edcSAsim Jamshed 			goto release_everything;
57276404edcSAsim Jamshed 		}
57376404edcSAsim Jamshed 		((*srv_states)[i])->srvconf.port = 0;
57476404edcSAsim Jamshed 		((*srv_states)[i])->srvconf.dont_daemonize =
57576404edcSAsim Jamshed 			first_entry->srvconf.dont_daemonize;
57676404edcSAsim Jamshed #if !(defined USE_MTCP || defined REUSEPORT)
57776404edcSAsim Jamshed 		//#ifndef USE_MTCP
57876404edcSAsim Jamshed 		((*srv_states)[i])->first_entry = first_entry;
57976404edcSAsim Jamshed #endif
58076404edcSAsim Jamshed 
58176404edcSAsim Jamshed 		/* set the struct by reading the conf file again... */
58276404edcSAsim Jamshed 		if (config_read(((*srv_states)[i]), conf_file))
58376404edcSAsim Jamshed 			goto release_everything;
58476404edcSAsim Jamshed 		buffer_copy_string(((*srv_states)[i])->srvconf.modules_dir,
58576404edcSAsim Jamshed 				   first_entry->srvconf.modules_dir->ptr);
58676404edcSAsim Jamshed 		/* ... and set the remaining as default. */
58776404edcSAsim Jamshed 		if (0 != config_set_defaults((*srv_states)[i])) {
58876404edcSAsim Jamshed 			log_error_write((*srv_states)[i], __FILE__, __LINE__, "s",
58976404edcSAsim Jamshed 					"setting default values failed");
59076404edcSAsim Jamshed 			goto release_everything;
59176404edcSAsim Jamshed 		}
59276404edcSAsim Jamshed 		/* load the plugins... i hope it doesn't mess things up */
59376404edcSAsim Jamshed 		if (plugins_load((*srv_states)[i])) {
59476404edcSAsim Jamshed 			log_error_write((*srv_states)[i], __FILE__, __LINE__, "s",
59576404edcSAsim Jamshed 					"loading plugins finally failed");
59676404edcSAsim Jamshed 			goto release_everything;
59776404edcSAsim Jamshed 		}
59876404edcSAsim Jamshed 		/* clone max_fds as well */
59976404edcSAsim Jamshed 		((*srv_states)[i])->max_fds = first_entry->max_fds;
60076404edcSAsim Jamshed 		/* clone max_conns as well */
60176404edcSAsim Jamshed 		((*srv_states)[i])->max_conns = first_entry->max_conns;
60276404edcSAsim Jamshed #ifdef USE_MTCP
60376404edcSAsim Jamshed 		/* clone listen backlog limit */
60476404edcSAsim Jamshed 		((*srv_states)[i])->listen_backlog = first_entry->listen_backlog;
60576404edcSAsim Jamshed #endif
60676404edcSAsim Jamshed 	}
60776404edcSAsim Jamshed 	return;
60876404edcSAsim Jamshed  release_everything:
60976404edcSAsim Jamshed 	/* release everything in reverse then */
61076404edcSAsim Jamshed 	while (i >= 0) {
61176404edcSAsim Jamshed 		server_free((*srv_states)[i]);
61276404edcSAsim Jamshed 		plugins_free((*srv_states)[i]);
61376404edcSAsim Jamshed 		i--;
61476404edcSAsim Jamshed 	}
61576404edcSAsim Jamshed 	free(*srv_states);
61676404edcSAsim Jamshed 	exit(EXIT_FAILURE);
61776404edcSAsim Jamshed }
61876404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
61976404edcSAsim Jamshed void *
start_server(void * svrptr)62076404edcSAsim Jamshed start_server(void *svrptr)
62176404edcSAsim Jamshed {
62276404edcSAsim Jamshed 	server *srv = (server *)svrptr;
62376404edcSAsim Jamshed 	size_t cpu = srv->cpu;
62476404edcSAsim Jamshed 	size_t i;
62576404edcSAsim Jamshed 
62676404edcSAsim Jamshed 	/* affinitize server to core `cpu' */
62776404edcSAsim Jamshed 	core_affinitize(cpu);
62876404edcSAsim Jamshed 
62976404edcSAsim Jamshed #ifdef USE_MTCP
63076404edcSAsim Jamshed 	/* initialize the per-cpu mctx context */
63176404edcSAsim Jamshed 	/* creating mtcp context first */
63276404edcSAsim Jamshed 	srv->mctx = mtcp_create_context(cpu);
63376404edcSAsim Jamshed 	if (!srv->mctx) {
63476404edcSAsim Jamshed 		fprintf(stderr, "Failed to create mtcp context!\n");
63576404edcSAsim Jamshed 		exit(EXIT_FAILURE);
63676404edcSAsim Jamshed 	}
63776404edcSAsim Jamshed 
63876404edcSAsim Jamshed 	/* adjust max fds to max_conns * 3 */
63976404edcSAsim Jamshed 	srv->max_fds = srv->max_conns * 3;
64076404edcSAsim Jamshed #else
64176404edcSAsim Jamshed 	/* register SIGINT signal handler */
64276404edcSAsim Jamshed 	signal(SIGINT, signal_handler);
64376404edcSAsim Jamshed 
64476404edcSAsim Jamshed #endif /* !USE_MTCP */
64576404edcSAsim Jamshed 
64676404edcSAsim Jamshed 	/* network backend initialization */
64776404edcSAsim Jamshed 	if (network_init(srv) == -1)
64876404edcSAsim Jamshed 		exit(EXIT_FAILURE);
64976404edcSAsim Jamshed #ifdef USE_MTCP
65076404edcSAsim Jamshed 	set_max_conns(srv, 0);
65176404edcSAsim Jamshed #else
65276404edcSAsim Jamshed 	set_max_conns(srv, 1);
65376404edcSAsim Jamshed #endif
65476404edcSAsim Jamshed 	load_plugins(srv);
65576404edcSAsim Jamshed 
65676404edcSAsim Jamshed 	/* Close stderr ASAP in the child process to make sure that nothing
65776404edcSAsim Jamshed 	 * is being written to that fd which may not be valid anymore. */
65876404edcSAsim Jamshed 	if (-1 == log_error_open(srv)) {
65976404edcSAsim Jamshed 		log_error_write(srv, __FILE__, __LINE__, "s",
66076404edcSAsim Jamshed 				"Opening errorlog failed. Going down.");
66176404edcSAsim Jamshed 		exit(EXIT_FAILURE);
66276404edcSAsim Jamshed 	}
66376404edcSAsim Jamshed 
66476404edcSAsim Jamshed 	if (HANDLER_GO_ON != plugins_call_set_defaults(srv)) {
66576404edcSAsim Jamshed 		log_error_write(srv, __FILE__, __LINE__, "s",
66676404edcSAsim Jamshed 				"Configuration of plugins failed. Going down.");
66776404edcSAsim Jamshed 		exit(EXIT_FAILURE);
66876404edcSAsim Jamshed 	}
66976404edcSAsim Jamshed 
67076404edcSAsim Jamshed 	/* register fdevent framework first */
67176404edcSAsim Jamshed 	initialize_fd_framework(srv);
67276404edcSAsim Jamshed 
67376404edcSAsim Jamshed 	/* and... finally the 'main-loop' */
67476404edcSAsim Jamshed 	/*-------------------------------------------------------------------------------*/
67576404edcSAsim Jamshed 	/* main-loop */
67676404edcSAsim Jamshed 	while (!srv_shutdown) {
67776404edcSAsim Jamshed 		int n;
67876404edcSAsim Jamshed 		size_t ndx;
67976404edcSAsim Jamshed 		time_t min_ts;
68076404edcSAsim Jamshed 
68176404edcSAsim Jamshed 		if (handle_sig_hup) {
68276404edcSAsim Jamshed 			handler_t r;
68376404edcSAsim Jamshed 
68476404edcSAsim Jamshed 			/* reset notification */
68576404edcSAsim Jamshed 			handle_sig_hup = 0;
68676404edcSAsim Jamshed 
68776404edcSAsim Jamshed 
68876404edcSAsim Jamshed 			/* cycle logfiles */
68976404edcSAsim Jamshed 
69076404edcSAsim Jamshed 			switch(r = plugins_call_handle_sighup(srv)) {
69176404edcSAsim Jamshed 			case HANDLER_GO_ON:
69276404edcSAsim Jamshed 				break;
69376404edcSAsim Jamshed 			default:
69476404edcSAsim Jamshed 				log_error_write(srv, __FILE__, __LINE__, "sd", "sighup-handler return with an error", r);
69576404edcSAsim Jamshed 				break;
69676404edcSAsim Jamshed 			}
69776404edcSAsim Jamshed 
69876404edcSAsim Jamshed 			if (-1 == log_error_cycle(srv)) {
69976404edcSAsim Jamshed 				log_error_write(srv, __FILE__, __LINE__, "s", "cycling errorlog failed, dying");
70076404edcSAsim Jamshed 
70176404edcSAsim Jamshed 				exit(EXIT_FAILURE);
70276404edcSAsim Jamshed 			} else {
70376404edcSAsim Jamshed #ifdef HAVE_SIGACTION
70476404edcSAsim Jamshed 				log_error_write(srv, __FILE__, __LINE__, "sdsd",
70576404edcSAsim Jamshed 					"logfiles cycled UID =",
70676404edcSAsim Jamshed 					last_sighup_info.si_uid,
70776404edcSAsim Jamshed 					"PID =",
70876404edcSAsim Jamshed 					last_sighup_info.si_pid);
70976404edcSAsim Jamshed #else
71076404edcSAsim Jamshed 				log_error_write(srv, __FILE__, __LINE__, "s",
71176404edcSAsim Jamshed 					"logfiles cycled");
71276404edcSAsim Jamshed #endif
71376404edcSAsim Jamshed 			}
71476404edcSAsim Jamshed 		}
71576404edcSAsim Jamshed 
71676404edcSAsim Jamshed 		if (handle_sig_alarm) {
71776404edcSAsim Jamshed 			/* a new second */
71876404edcSAsim Jamshed 
71976404edcSAsim Jamshed #ifdef USE_ALARM
72076404edcSAsim Jamshed 			/* reset notification */
72176404edcSAsim Jamshed 			handle_sig_alarm = 0;
72276404edcSAsim Jamshed #endif
72376404edcSAsim Jamshed 
72476404edcSAsim Jamshed 			/* get current time */
72576404edcSAsim Jamshed 			min_ts = time(NULL);
72676404edcSAsim Jamshed 
72776404edcSAsim Jamshed 			if (min_ts != srv->cur_ts) {
72876404edcSAsim Jamshed 				int cs = 0;
72976404edcSAsim Jamshed 				connections *conns = srv->conns;
73076404edcSAsim Jamshed 				handler_t r;
73176404edcSAsim Jamshed 
73276404edcSAsim Jamshed 				switch(r = plugins_call_handle_trigger(srv)) {
73376404edcSAsim Jamshed 				case HANDLER_GO_ON:
73476404edcSAsim Jamshed 					break;
73576404edcSAsim Jamshed 				case HANDLER_ERROR:
73676404edcSAsim Jamshed 					log_error_write(srv, __FILE__, __LINE__, "s", "one of the triggers failed");
73776404edcSAsim Jamshed 					break;
73876404edcSAsim Jamshed 				default:
73976404edcSAsim Jamshed 					log_error_write(srv, __FILE__, __LINE__, "d", r);
74076404edcSAsim Jamshed 					break;
74176404edcSAsim Jamshed 				}
74276404edcSAsim Jamshed 
74376404edcSAsim Jamshed 				/* trigger waitpid */
74476404edcSAsim Jamshed 				srv->cur_ts = min_ts;
74576404edcSAsim Jamshed 
74676404edcSAsim Jamshed 				/* cleanup stat-cache */
74776404edcSAsim Jamshed 				stat_cache_trigger_cleanup(srv);
74876404edcSAsim Jamshed 				/**
74976404edcSAsim Jamshed 				 * check all connections for timeouts
75076404edcSAsim Jamshed 				 *
75176404edcSAsim Jamshed 				 */
75276404edcSAsim Jamshed 				for (ndx = 0; ndx < conns->used; ndx++) {
75376404edcSAsim Jamshed 					int changed = 0;
75476404edcSAsim Jamshed 					connection *con;
75576404edcSAsim Jamshed 					int t_diff;
75676404edcSAsim Jamshed 
75776404edcSAsim Jamshed 					con = conns->ptr[ndx];
75876404edcSAsim Jamshed 
75976404edcSAsim Jamshed 					if (con->state == CON_STATE_READ ||
76076404edcSAsim Jamshed 					    con->state == CON_STATE_READ_POST) {
76176404edcSAsim Jamshed 						if (con->request_count == 1) {
76276404edcSAsim Jamshed 							if (srv->cur_ts - con->read_idle_ts > con->conf.max_read_idle) {
76376404edcSAsim Jamshed 								/* time - out */
76476404edcSAsim Jamshed #if 0
76576404edcSAsim Jamshed 								log_error_write(srv, __FILE__, __LINE__, "sd",
76676404edcSAsim Jamshed 										"connection closed - read-timeout:", con->fd);
76776404edcSAsim Jamshed #endif
76876404edcSAsim Jamshed 								connection_set_state(srv, con, CON_STATE_ERROR);
76976404edcSAsim Jamshed 								changed = 1;
77076404edcSAsim Jamshed 							}
77176404edcSAsim Jamshed 						} else {
77276404edcSAsim Jamshed 							if (srv->cur_ts - con->read_idle_ts > con->keep_alive_idle) {
77376404edcSAsim Jamshed 								/* time - out */
77476404edcSAsim Jamshed #if 0
77576404edcSAsim Jamshed 								log_error_write(srv, __FILE__, __LINE__, "sd",
77676404edcSAsim Jamshed 										"connection closed - read-timeout:", con->fd);
77776404edcSAsim Jamshed #endif
77876404edcSAsim Jamshed 								connection_set_state(srv, con, CON_STATE_ERROR);
77976404edcSAsim Jamshed 								changed = 1;
78076404edcSAsim Jamshed 							}
78176404edcSAsim Jamshed 						}
78276404edcSAsim Jamshed 					}
78376404edcSAsim Jamshed 
78476404edcSAsim Jamshed 					if ((con->state == CON_STATE_WRITE) &&
78576404edcSAsim Jamshed 					    (con->write_request_ts != 0)) {
78676404edcSAsim Jamshed #if 0
78776404edcSAsim Jamshed 						if (srv->cur_ts - con->write_request_ts > 60) {
78876404edcSAsim Jamshed 							log_error_write(srv, __FILE__, __LINE__, "sdd",
78976404edcSAsim Jamshed 									"connection closed - pre-write-request-timeout:", con->fd, srv->cur_ts - con->write_request_ts);
79076404edcSAsim Jamshed 						}
79176404edcSAsim Jamshed #endif
79276404edcSAsim Jamshed 
79376404edcSAsim Jamshed 						if (srv->cur_ts - con->write_request_ts > con->conf.max_write_idle) {
79476404edcSAsim Jamshed 							/* time - out */
79576404edcSAsim Jamshed 							if (con->conf.log_timeouts) {
79676404edcSAsim Jamshed 								log_error_write(srv, __FILE__, __LINE__, "sbsosds",
79776404edcSAsim Jamshed 									"NOTE: a request for",
79876404edcSAsim Jamshed 									con->request.uri,
79976404edcSAsim Jamshed 									"timed out after writing",
80076404edcSAsim Jamshed 									con->bytes_written,
80176404edcSAsim Jamshed 									"bytes. We waited",
80276404edcSAsim Jamshed 									(int)con->conf.max_write_idle,
80376404edcSAsim Jamshed 									"seconds. If this a problem increase server.max-write-idle");
80476404edcSAsim Jamshed 							}
80576404edcSAsim Jamshed 							connection_set_state(srv, con, CON_STATE_ERROR);
80676404edcSAsim Jamshed 							changed = 1;
80776404edcSAsim Jamshed 						}
80876404edcSAsim Jamshed 					}
80976404edcSAsim Jamshed 
81076404edcSAsim Jamshed 					if (con->state == CON_STATE_CLOSE && (srv->cur_ts - con->close_timeout_ts > HTTP_LINGER_TIMEOUT)) {
81176404edcSAsim Jamshed 						changed = 1;
81276404edcSAsim Jamshed 					}
81376404edcSAsim Jamshed 
81476404edcSAsim Jamshed 					/* we don't like div by zero */
81576404edcSAsim Jamshed 					if (0 == (t_diff = srv->cur_ts - con->connection_start)) t_diff = 1;
81676404edcSAsim Jamshed 
81776404edcSAsim Jamshed 					if (con->traffic_limit_reached &&
81876404edcSAsim Jamshed 					    (con->conf.kbytes_per_second == 0 ||
81976404edcSAsim Jamshed 					     ((con->bytes_written / t_diff) < con->conf.kbytes_per_second * 1024))) {
82076404edcSAsim Jamshed 						/* enable connection again */
82176404edcSAsim Jamshed 						con->traffic_limit_reached = 0;
82276404edcSAsim Jamshed 
82376404edcSAsim Jamshed 						changed = 1;
82476404edcSAsim Jamshed 					}
82576404edcSAsim Jamshed 
82676404edcSAsim Jamshed 					if (changed) {
82776404edcSAsim Jamshed 						connection_state_machine(srv, con);
82876404edcSAsim Jamshed 					}
82976404edcSAsim Jamshed 					con->bytes_written_cur_second = 0;
83076404edcSAsim Jamshed 					*(con->conf.global_bytes_per_second_cnt_ptr) = 0;
83176404edcSAsim Jamshed 
83276404edcSAsim Jamshed #if 0
83376404edcSAsim Jamshed 					if (cs == 0) {
83476404edcSAsim Jamshed 						fprintf(stderr, "connection-state: ");
83576404edcSAsim Jamshed 						cs = 1;
83676404edcSAsim Jamshed 					}
83776404edcSAsim Jamshed 
83876404edcSAsim Jamshed 					fprintf(stderr, "c[%d,%d]: %s ",
83976404edcSAsim Jamshed 						con->fd,
84076404edcSAsim Jamshed 						con->fcgi.fd,
84176404edcSAsim Jamshed 						connection_get_state(con->state));
84276404edcSAsim Jamshed #endif
84376404edcSAsim Jamshed 				}
84476404edcSAsim Jamshed 
84576404edcSAsim Jamshed 				if (cs == 1) fprintf(stderr, "\n");
84676404edcSAsim Jamshed 			}
84776404edcSAsim Jamshed 		}
84876404edcSAsim Jamshed 
84976404edcSAsim Jamshed 		if (srv->sockets_disabled) {
85076404edcSAsim Jamshed 			/* our server sockets are disabled, why ? */
85176404edcSAsim Jamshed 
85276404edcSAsim Jamshed 			if ((srv->cur_fds + srv->want_fds < srv->max_fds * 8 / 10) && /* we have enough unused fds */
85376404edcSAsim Jamshed 			    (srv->conns->used <= srv->max_conns * 9 / 10) &&
85476404edcSAsim Jamshed 			    (0 == graceful_shutdown)) {
85576404edcSAsim Jamshed 				for (i = 0; i < srv->srv_sockets.used; i++) {
85676404edcSAsim Jamshed 					server_socket *srv_socket = srv->srv_sockets.ptr[i];
85776404edcSAsim Jamshed 					fdevent_event_set(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd, FDEVENT_IN);
85876404edcSAsim Jamshed 				}
85976404edcSAsim Jamshed 
86076404edcSAsim Jamshed 				log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets enabled again");
86176404edcSAsim Jamshed 
86276404edcSAsim Jamshed 				srv->sockets_disabled = 0;
86376404edcSAsim Jamshed 			}
86476404edcSAsim Jamshed 		} else {
86576404edcSAsim Jamshed 			if ((srv->cur_fds + srv->want_fds > srv->max_fds * 9 / 10) || /* out of fds */
86676404edcSAsim Jamshed 			    (srv->conns->used >= srv->max_conns) || /* out of connections */
86776404edcSAsim Jamshed 			    (graceful_shutdown)) { /* graceful_shutdown */
86876404edcSAsim Jamshed 
86976404edcSAsim Jamshed 				/* disable server-fds */
87076404edcSAsim Jamshed 
87176404edcSAsim Jamshed 				for (i = 0; i < srv->srv_sockets.used; i++) {
87276404edcSAsim Jamshed 					server_socket *srv_socket = srv->srv_sockets.ptr[i];
87376404edcSAsim Jamshed 					fdevent_event_del(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd);
87476404edcSAsim Jamshed 
87576404edcSAsim Jamshed 					if (graceful_shutdown) {
87676404edcSAsim Jamshed 						/* we don't want this socket anymore,
87776404edcSAsim Jamshed 						 *
87876404edcSAsim Jamshed 						 * closing it right away will make it possible for
87976404edcSAsim Jamshed 						 * the next lighttpd to take over (graceful restart)
88076404edcSAsim Jamshed 						 *  */
88176404edcSAsim Jamshed 
88276404edcSAsim Jamshed 						fdevent_unregister(srv->ev, srv_socket->fd);
88376404edcSAsim Jamshed #ifdef USE_MTCP
88476404edcSAsim Jamshed 						mtcp_close(srv->mctx, srv_socket->fd);
88576404edcSAsim Jamshed #else
88676404edcSAsim Jamshed 						close(srv_socket->fd);
88776404edcSAsim Jamshed #endif
88876404edcSAsim Jamshed 						srv_socket->fd = -1;
88976404edcSAsim Jamshed 
89076404edcSAsim Jamshed 						/* network_close() will cleanup after us */
89176404edcSAsim Jamshed 
89276404edcSAsim Jamshed 						if (srv->srvconf.pid_file->used &&
89376404edcSAsim Jamshed 						    srv->srvconf.changeroot->used == 0) {
89476404edcSAsim Jamshed 							if (0 != unlink(srv->srvconf.pid_file->ptr)) {
89576404edcSAsim Jamshed 								if (errno != EACCES && errno != EPERM) {
89676404edcSAsim Jamshed 									log_error_write(srv, __FILE__, __LINE__, "sbds",
89776404edcSAsim Jamshed 											"unlink failed for:",
89876404edcSAsim Jamshed 											srv->srvconf.pid_file,
89976404edcSAsim Jamshed 											errno,
90076404edcSAsim Jamshed 											strerror(errno));
90176404edcSAsim Jamshed 								}
90276404edcSAsim Jamshed 							}
90376404edcSAsim Jamshed 						}
90476404edcSAsim Jamshed 					}
90576404edcSAsim Jamshed 				}
90676404edcSAsim Jamshed 
90776404edcSAsim Jamshed 				if (graceful_shutdown) {
90876404edcSAsim Jamshed 					log_error_write(srv, __FILE__, __LINE__, "s", "[note] graceful shutdown started");
90976404edcSAsim Jamshed 				} else if (srv->conns->used >= srv->max_conns) {
91076404edcSAsim Jamshed 					log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets disabled, connection limit reached");
91176404edcSAsim Jamshed 				} else {
91276404edcSAsim Jamshed 					log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets disabled, out-of-fds");
91376404edcSAsim Jamshed 				}
91476404edcSAsim Jamshed 
91576404edcSAsim Jamshed 				srv->sockets_disabled = 1;
91676404edcSAsim Jamshed 			}
91776404edcSAsim Jamshed 		}
91876404edcSAsim Jamshed 
91976404edcSAsim Jamshed 		if (graceful_shutdown && srv->conns->used == 0) {
92076404edcSAsim Jamshed 			/* we are in graceful shutdown phase and all connections are closed
92176404edcSAsim Jamshed 			 * we are ready to terminate without harming anyone */
92276404edcSAsim Jamshed 			srv_shutdown = 1;
92376404edcSAsim Jamshed 		}
92476404edcSAsim Jamshed 
92576404edcSAsim Jamshed 		/* we still have some fds to share */
92676404edcSAsim Jamshed 		if (srv->want_fds) {
92776404edcSAsim Jamshed 			/* check the fdwaitqueue for waiting fds */
92876404edcSAsim Jamshed 			int free_fds = srv->max_fds - srv->cur_fds - 16;
92976404edcSAsim Jamshed 			connection *con;
93076404edcSAsim Jamshed 
93176404edcSAsim Jamshed 			for (; free_fds > 0 && NULL != (con = fdwaitqueue_unshift(srv, srv->fdwaitqueue)); free_fds--) {
93276404edcSAsim Jamshed 				connection_state_machine(srv, con);
93376404edcSAsim Jamshed 
93476404edcSAsim Jamshed 				srv->want_fds--;
93576404edcSAsim Jamshed 			}
93676404edcSAsim Jamshed 		}
93776404edcSAsim Jamshed 
93876404edcSAsim Jamshed 		if ((n = fdevent_poll(srv->ev, -1/*1000*/)) > 0) {
93976404edcSAsim Jamshed 			/* n is the number of events */
94076404edcSAsim Jamshed 			int revents;
94176404edcSAsim Jamshed 			int fd_ndx;
94276404edcSAsim Jamshed #if 0
94376404edcSAsim Jamshed 			if (n > 0) {
94476404edcSAsim Jamshed 				log_error_write(srv, __FILE__, __LINE__, "sd",
94576404edcSAsim Jamshed 						"polls:", n);
94676404edcSAsim Jamshed 			}
94776404edcSAsim Jamshed #endif
94876404edcSAsim Jamshed 			fd_ndx = -1;
94976404edcSAsim Jamshed 			do {
95076404edcSAsim Jamshed 				fdevent_handler handler;
95176404edcSAsim Jamshed 				void *context;
95276404edcSAsim Jamshed 				handler_t r;
95376404edcSAsim Jamshed 				int fd;
95476404edcSAsim Jamshed 
95576404edcSAsim Jamshed 				fd_ndx  = fdevent_event_next_fdndx (srv->ev, fd_ndx);
95676404edcSAsim Jamshed 				if (-1 == fd_ndx) break; /* not all fdevent handlers know how many fds got an event */
95776404edcSAsim Jamshed 
95876404edcSAsim Jamshed 				revents = fdevent_event_get_revent (srv->ev, fd_ndx);
95976404edcSAsim Jamshed 				fd      = fdevent_event_get_fd     (srv->ev, fd_ndx);
96076404edcSAsim Jamshed 				handler = fdevent_get_handler(srv->ev, fd);
96176404edcSAsim Jamshed 				context = fdevent_get_context(srv->ev, fd);
96276404edcSAsim Jamshed 
96376404edcSAsim Jamshed 				/* connection_handle_fdevent needs a joblist_append */
96476404edcSAsim Jamshed #if 0
96576404edcSAsim Jamshed 				log_error_write(srv, __FILE__, __LINE__, "sdd",
96676404edcSAsim Jamshed 						"event for", fd, revents);
96776404edcSAsim Jamshed #endif
96876404edcSAsim Jamshed 				switch (r = (*handler)(srv, context, revents)) {
96976404edcSAsim Jamshed 				case HANDLER_FINISHED:
97076404edcSAsim Jamshed 				case HANDLER_GO_ON:
97176404edcSAsim Jamshed 				case HANDLER_WAIT_FOR_EVENT:
97276404edcSAsim Jamshed 				case HANDLER_WAIT_FOR_FD:
97376404edcSAsim Jamshed 					break;
97476404edcSAsim Jamshed 				case HANDLER_ERROR:
97576404edcSAsim Jamshed 					/* should never happen */
97676404edcSAsim Jamshed 					SEGFAULT();
97776404edcSAsim Jamshed 					break;
97876404edcSAsim Jamshed 				default:
97976404edcSAsim Jamshed 					log_error_write(srv, __FILE__, __LINE__, "d", r);
98076404edcSAsim Jamshed 					break;
98176404edcSAsim Jamshed 				}
98276404edcSAsim Jamshed 			} while (--n > 0);
98376404edcSAsim Jamshed 		} else if (n < 0 && errno != EINTR) {
98476404edcSAsim Jamshed 			log_error_write(srv, __FILE__, __LINE__, "ss",
98576404edcSAsim Jamshed 					"fdevent_poll failed:",
98676404edcSAsim Jamshed 					strerror(errno));
98776404edcSAsim Jamshed 		}
98876404edcSAsim Jamshed 
98976404edcSAsim Jamshed 		for (ndx = 0; ndx < srv->joblist->used; ndx++) {
99076404edcSAsim Jamshed 			connection *con = srv->joblist->ptr[ndx];
99176404edcSAsim Jamshed 			handler_t r;
99276404edcSAsim Jamshed 
99376404edcSAsim Jamshed 			connection_state_machine(srv, con);
99476404edcSAsim Jamshed 
99576404edcSAsim Jamshed 			switch(r = plugins_call_handle_joblist(srv, con)) {
99676404edcSAsim Jamshed 			case HANDLER_FINISHED:
99776404edcSAsim Jamshed 			case HANDLER_GO_ON:
99876404edcSAsim Jamshed 				break;
99976404edcSAsim Jamshed 			default:
100076404edcSAsim Jamshed 				log_error_write(srv, __FILE__, __LINE__, "d", r);
100176404edcSAsim Jamshed 				break;
100276404edcSAsim Jamshed 			}
100376404edcSAsim Jamshed 
100476404edcSAsim Jamshed 			con->in_joblist = 0;
100576404edcSAsim Jamshed 		}
100676404edcSAsim Jamshed 
100776404edcSAsim Jamshed 		srv->joblist->used = 0;
100876404edcSAsim Jamshed 	} /* end of `while (!srv_shutdown)` */
100976404edcSAsim Jamshed 	/*-------------------------------------------------------------------------------*/
101076404edcSAsim Jamshed #ifdef USE_MTCP
101176404edcSAsim Jamshed 	/* TODO - this will go somewhere else */
101276404edcSAsim Jamshed 	mtcp_destroy_context(srv->mctx);
101376404edcSAsim Jamshed #endif
101476404edcSAsim Jamshed 	pthread_exit(NULL);
101576404edcSAsim Jamshed 
101676404edcSAsim Jamshed 	return NULL;
101776404edcSAsim Jamshed }
101876404edcSAsim Jamshed #endif /* !MULTI_THREADED */
101976404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
102076404edcSAsim Jamshed static void
show_version(void)102176404edcSAsim Jamshed show_version (void) {
102276404edcSAsim Jamshed #ifdef USE_OPENSSL
102376404edcSAsim Jamshed # define TEXT_SSL " (ssl)"
102476404edcSAsim Jamshed #else
102576404edcSAsim Jamshed # define TEXT_SSL
102676404edcSAsim Jamshed #endif
102776404edcSAsim Jamshed 	char *b = PACKAGE_DESC TEXT_SSL \
102876404edcSAsim Jamshed " - a light and fast webserver\n" \
102976404edcSAsim Jamshed "Build-Date: " __DATE__ " " __TIME__ "\n";
103076404edcSAsim Jamshed ;
103176404edcSAsim Jamshed #undef TEXT_SSL
103276404edcSAsim Jamshed 	write(STDOUT_FILENO, b, strlen(b));
103376404edcSAsim Jamshed }
103476404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
103576404edcSAsim Jamshed static void
show_features(void)103676404edcSAsim Jamshed show_features(void) {
103776404edcSAsim Jamshed 	const char features[] = ""
103876404edcSAsim Jamshed #ifdef USE_SELECT
103976404edcSAsim Jamshed 		"\t+ select (generic)\n"
104076404edcSAsim Jamshed #else
104176404edcSAsim Jamshed 		"\t- select (generic)\n"
104276404edcSAsim Jamshed #endif
104376404edcSAsim Jamshed #ifdef USE_POLL
104476404edcSAsim Jamshed 		"\t+ poll (Unix)\n"
104576404edcSAsim Jamshed #else
104676404edcSAsim Jamshed 		"\t- poll (Unix)\n"
104776404edcSAsim Jamshed #endif
104876404edcSAsim Jamshed #ifdef USE_LINUX_SIGIO
104976404edcSAsim Jamshed 		"\t+ rt-signals (Linux 2.4+)\n"
105076404edcSAsim Jamshed #else
105176404edcSAsim Jamshed 		"\t- rt-signals (Linux 2.4+)\n"
105276404edcSAsim Jamshed #endif
105376404edcSAsim Jamshed #ifdef USE_LINUX_EPOLL
105476404edcSAsim Jamshed 		"\t+ epoll (Linux 2.6)\n"
105576404edcSAsim Jamshed #else
105676404edcSAsim Jamshed 		"\t- epoll (Linux 2.6)\n"
105776404edcSAsim Jamshed #endif
105876404edcSAsim Jamshed #ifdef USE_SOLARIS_DEVPOLL
105976404edcSAsim Jamshed 		"\t+ /dev/poll (Solaris)\n"
106076404edcSAsim Jamshed #else
106176404edcSAsim Jamshed 		"\t- /dev/poll (Solaris)\n"
106276404edcSAsim Jamshed #endif
106376404edcSAsim Jamshed #ifdef USE_SOLARIS_PORT
106476404edcSAsim Jamshed 		"\t+ eventports (Solaris)\n"
106576404edcSAsim Jamshed #else
106676404edcSAsim Jamshed 		"\t- eventports (Solaris)\n"
106776404edcSAsim Jamshed #endif
106876404edcSAsim Jamshed #ifdef USE_FREEBSD_KQUEUE
106976404edcSAsim Jamshed 		"\t+ kqueue (FreeBSD)\n"
107076404edcSAsim Jamshed #else
107176404edcSAsim Jamshed 		"\t- kqueue (FreeBSD)\n"
107276404edcSAsim Jamshed #endif
107376404edcSAsim Jamshed #ifdef USE_LIBEV
107476404edcSAsim Jamshed 		"\t+ libev (generic)\n"
107576404edcSAsim Jamshed #else
107676404edcSAsim Jamshed 		"\t- libev (generic)\n"
107776404edcSAsim Jamshed #endif
107876404edcSAsim Jamshed 		"\nNetwork handler:\n\n"
107976404edcSAsim Jamshed #if defined USE_LINUX_SENDFILE
108076404edcSAsim Jamshed 		"\t+ linux-sendfile\n"
108176404edcSAsim Jamshed #else
108276404edcSAsim Jamshed 		"\t- linux-sendfile\n"
108376404edcSAsim Jamshed #endif
108476404edcSAsim Jamshed #if defined USE_FREEBSD_SENDFILE
108576404edcSAsim Jamshed 		"\t+ freebsd-sendfile\n"
108676404edcSAsim Jamshed #else
108776404edcSAsim Jamshed 		"\t- freebsd-sendfile\n"
108876404edcSAsim Jamshed #endif
108976404edcSAsim Jamshed #if defined USE_SOLARIS_SENDFILEV
109076404edcSAsim Jamshed 		"\t+ solaris-sendfilev\n"
109176404edcSAsim Jamshed #else
109276404edcSAsim Jamshed 		"\t- solaris-sendfilev\n"
109376404edcSAsim Jamshed #endif
109476404edcSAsim Jamshed #if defined USE_WRITEV
109576404edcSAsim Jamshed 		"\t+ writev\n"
109676404edcSAsim Jamshed #else
109776404edcSAsim Jamshed 		"\t- writev\n"
109876404edcSAsim Jamshed #endif
109976404edcSAsim Jamshed 		"\t+ write\n"
110076404edcSAsim Jamshed #ifdef USE_MMAP
110176404edcSAsim Jamshed 		"\t+ mmap support\n"
110276404edcSAsim Jamshed #else
110376404edcSAsim Jamshed 		"\t- mmap support\n"
110476404edcSAsim Jamshed #endif
110576404edcSAsim Jamshed 		"\nFeatures:\n\n"
110676404edcSAsim Jamshed #ifdef HAVE_IPV6
110776404edcSAsim Jamshed 		"\t+ IPv6 support\n"
110876404edcSAsim Jamshed #else
110976404edcSAsim Jamshed 		"\t- IPv6 support\n"
111076404edcSAsim Jamshed #endif
111176404edcSAsim Jamshed #if defined HAVE_ZLIB_H && defined HAVE_LIBZ
111276404edcSAsim Jamshed 		"\t+ zlib support\n"
111376404edcSAsim Jamshed #else
111476404edcSAsim Jamshed 		"\t- zlib support\n"
111576404edcSAsim Jamshed #endif
111676404edcSAsim Jamshed #if defined HAVE_BZLIB_H && defined HAVE_LIBBZ2
111776404edcSAsim Jamshed 		"\t+ bzip2 support\n"
111876404edcSAsim Jamshed #else
111976404edcSAsim Jamshed 		"\t- bzip2 support\n"
112076404edcSAsim Jamshed #endif
112176404edcSAsim Jamshed #ifdef HAVE_LIBCRYPT
112276404edcSAsim Jamshed 		"\t+ crypt support\n"
112376404edcSAsim Jamshed #else
112476404edcSAsim Jamshed 		"\t- crypt support\n"
112576404edcSAsim Jamshed #endif
112676404edcSAsim Jamshed #ifdef USE_OPENSSL
112776404edcSAsim Jamshed 		"\t+ SSL Support\n"
112876404edcSAsim Jamshed #else
112976404edcSAsim Jamshed 		"\t- SSL Support\n"
113076404edcSAsim Jamshed #endif
113176404edcSAsim Jamshed #ifdef USE_MTCP
113276404edcSAsim Jamshed 		"\t+ MTCP Support\n"
113376404edcSAsim Jamshed #else
113476404edcSAsim Jamshed 		"\t- MTCP Support\n"
113576404edcSAsim Jamshed #endif
113676404edcSAsim Jamshed #ifdef HAVE_LIBPCRE
113776404edcSAsim Jamshed 		"\t+ PCRE support\n"
113876404edcSAsim Jamshed #else
113976404edcSAsim Jamshed 		"\t- PCRE support\n"
114076404edcSAsim Jamshed #endif
114176404edcSAsim Jamshed #ifdef HAVE_MYSQL
114276404edcSAsim Jamshed 		"\t+ mySQL support\n"
114376404edcSAsim Jamshed #else
114476404edcSAsim Jamshed 		"\t- mySQL support\n"
114576404edcSAsim Jamshed #endif
114676404edcSAsim Jamshed #if defined(HAVE_LDAP_H) && defined(HAVE_LBER_H) && defined(HAVE_LIBLDAP) && defined(HAVE_LIBLBER)
114776404edcSAsim Jamshed 		"\t+ LDAP support\n"
114876404edcSAsim Jamshed #else
114976404edcSAsim Jamshed 		"\t- LDAP support\n"
115076404edcSAsim Jamshed #endif
115176404edcSAsim Jamshed #ifdef HAVE_MEMCACHE_H
115276404edcSAsim Jamshed 		"\t+ memcached support\n"
115376404edcSAsim Jamshed #else
115476404edcSAsim Jamshed 		"\t- memcached support\n"
115576404edcSAsim Jamshed #endif
115676404edcSAsim Jamshed #ifdef HAVE_FAM_H
115776404edcSAsim Jamshed 		"\t+ FAM support\n"
115876404edcSAsim Jamshed #else
115976404edcSAsim Jamshed 		"\t- FAM support\n"
116076404edcSAsim Jamshed #endif
116176404edcSAsim Jamshed #ifdef HAVE_LUA_H
116276404edcSAsim Jamshed 		"\t+ LUA support\n"
116376404edcSAsim Jamshed #else
116476404edcSAsim Jamshed 		"\t- LUA support\n"
116576404edcSAsim Jamshed #endif
116676404edcSAsim Jamshed #ifdef HAVE_LIBXML_H
116776404edcSAsim Jamshed 		"\t+ xml support\n"
116876404edcSAsim Jamshed #else
116976404edcSAsim Jamshed 		"\t- xml support\n"
117076404edcSAsim Jamshed #endif
117176404edcSAsim Jamshed #ifdef HAVE_SQLITE3_H
117276404edcSAsim Jamshed 		"\t+ SQLite support\n"
117376404edcSAsim Jamshed #else
117476404edcSAsim Jamshed 		"\t- SQLite support\n"
117576404edcSAsim Jamshed #endif
117676404edcSAsim Jamshed #ifdef HAVE_GDBM_H
117776404edcSAsim Jamshed 		"\t+ GDBM support\n"
117876404edcSAsim Jamshed #else
117976404edcSAsim Jamshed 		"\t- GDBM support\n"
118076404edcSAsim Jamshed #endif
118176404edcSAsim Jamshed 		"\n";
118276404edcSAsim Jamshed 	show_version();
118376404edcSAsim Jamshed 	printf("\nEvent Handlers:\n\n%s", features);
118476404edcSAsim Jamshed }
118576404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
118676404edcSAsim Jamshed static void
show_help(void)118776404edcSAsim Jamshed show_help(void) {
118876404edcSAsim Jamshed #ifdef USE_OPENSSL
118976404edcSAsim Jamshed # define TEXT_SSL " (ssl)"
119076404edcSAsim Jamshed #else
119176404edcSAsim Jamshed # define TEXT_SSL
119276404edcSAsim Jamshed #endif
119376404edcSAsim Jamshed 	char *b = PACKAGE_DESC TEXT_SSL " ("__DATE__ " " __TIME__ ")" \
119476404edcSAsim Jamshed " - a light and fast webserver\n" \
119576404edcSAsim Jamshed "usage:\n" \
119676404edcSAsim Jamshed " -f <name>  filename of the config-file\n" \
119776404edcSAsim Jamshed " -m <name>  module directory (default: "LIBRARY_DIR")\n" \
119876404edcSAsim Jamshed " -p         print the parsed config-file in internal form, and exit\n" \
1199*40fa1854SAsim Jamshed " -n <#cpus> number of cpu cores that lighttpd will use\n" \
120076404edcSAsim Jamshed " -t         test the config-file, and exit\n" \
120176404edcSAsim Jamshed " -D         don't go to background (default: go to background)\n" \
120276404edcSAsim Jamshed " -v         show version\n" \
120376404edcSAsim Jamshed " -V         show compile-time features\n" \
120476404edcSAsim Jamshed " -h         show this help\n" \
120576404edcSAsim Jamshed "\n"
120676404edcSAsim Jamshed ;
120776404edcSAsim Jamshed #undef TEXT_SSL
120876404edcSAsim Jamshed #undef TEXT_IPV6
120976404edcSAsim Jamshed 	write(STDOUT_FILENO, b, strlen(b));
121076404edcSAsim Jamshed }
121176404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
121276404edcSAsim Jamshed int
main(int argc,char ** argv)121376404edcSAsim Jamshed main(int argc, char **argv) {
121476404edcSAsim Jamshed #ifdef MULTI_THREADED
121576404edcSAsim Jamshed 	server **srv_states = NULL;
121676404edcSAsim Jamshed 	char *conf_file = NULL;
121776404edcSAsim Jamshed #ifdef USE_MTCP
121876404edcSAsim Jamshed 	struct mtcp_conf mcfg;
121976404edcSAsim Jamshed #endif
122076404edcSAsim Jamshed #endif
122176404edcSAsim Jamshed 	/*
122276404edcSAsim Jamshed 	 * The introduction of MTCP slightly changes the purpose of *srv.
122376404edcSAsim Jamshed 	 * *srv will always hold the srv state info for core 0.
122476404edcSAsim Jamshed 	 *
122576404edcSAsim Jamshed 	 * When compiled without --lib-mtcp, *srv is used as the default
122676404edcSAsim Jamshed 	 * version.
122776404edcSAsim Jamshed 	 */
122876404edcSAsim Jamshed 	server *srv = NULL;
122976404edcSAsim Jamshed 	int print_config = 0;
123076404edcSAsim Jamshed 	int test_config = 0;
123176404edcSAsim Jamshed 	int i_am_root;
123276404edcSAsim Jamshed 	int o;
123376404edcSAsim Jamshed 	int num_childs = 0;
123476404edcSAsim Jamshed 	int pid_fd = -1;
123576404edcSAsim Jamshed 	size_t i;
123676404edcSAsim Jamshed 	struct group *grp = NULL;
123776404edcSAsim Jamshed 	struct passwd *pwd = NULL;
123876404edcSAsim Jamshed #ifdef HAVE_SIGACTION
123976404edcSAsim Jamshed 	struct sigaction act;
124076404edcSAsim Jamshed #endif
124176404edcSAsim Jamshed #ifdef HAVE_GETRLIMIT
124276404edcSAsim Jamshed 	struct rlimit rlim;
124376404edcSAsim Jamshed #endif
124476404edcSAsim Jamshed 
124576404edcSAsim Jamshed #ifdef USE_ALARM
124676404edcSAsim Jamshed 	struct itimerval interval;
124776404edcSAsim Jamshed 
124876404edcSAsim Jamshed 	interval.it_interval.tv_sec = 1;
124976404edcSAsim Jamshed 	interval.it_interval.tv_usec = 0;
125076404edcSAsim Jamshed 	interval.it_value.tv_sec = 1;
125176404edcSAsim Jamshed 	interval.it_value.tv_usec = 0;
125276404edcSAsim Jamshed #endif
125376404edcSAsim Jamshed #ifdef MULTI_THREADED
125476404edcSAsim Jamshed 	/* create the cpu variable to facilitate multi-threading framework */
125576404edcSAsim Jamshed 	size_t cpus = -1;
125676404edcSAsim Jamshed #endif
125776404edcSAsim Jamshed 
125876404edcSAsim Jamshed 
125976404edcSAsim Jamshed 	/* for nice %b handling in strfime() */
126076404edcSAsim Jamshed 	setlocale(LC_TIME, "C");
126176404edcSAsim Jamshed 
126276404edcSAsim Jamshed 	if (NULL == (srv = server_init())) {
126376404edcSAsim Jamshed 		fprintf(stderr, "did this really happen?\n");
126476404edcSAsim Jamshed 		return EXIT_FAILURE;
126576404edcSAsim Jamshed 	}
126676404edcSAsim Jamshed 
126776404edcSAsim Jamshed 	/* init structs done */
126876404edcSAsim Jamshed #ifdef HAVE_GETUID
126976404edcSAsim Jamshed 	i_am_root = (getuid() == 0);
127076404edcSAsim Jamshed #else
127176404edcSAsim Jamshed 	i_am_root = 0;
127276404edcSAsim Jamshed #endif
127376404edcSAsim Jamshed 
127476404edcSAsim Jamshed 	srv->srvconf.port = 0;
127576404edcSAsim Jamshed 	srv->srvconf.dont_daemonize = 0;
127676404edcSAsim Jamshed 
127776404edcSAsim Jamshed 	while(-1 != (o = getopt(argc, argv, "f:m:n:hvVDpt"))) {
127876404edcSAsim Jamshed 		switch(o) {
127976404edcSAsim Jamshed 		case 'f':
128076404edcSAsim Jamshed 			if (srv->config_storage) {
128176404edcSAsim Jamshed 				log_error_write(srv, __FILE__, __LINE__, "s",
128276404edcSAsim Jamshed 						"Can only read one config file. Use the include command to use multiple config files.");
128376404edcSAsim Jamshed 
128476404edcSAsim Jamshed 				server_free(srv);
128576404edcSAsim Jamshed 				return EXIT_FAILURE;
128676404edcSAsim Jamshed 			}
128776404edcSAsim Jamshed #ifdef MULTI_THREADED
128876404edcSAsim Jamshed 			/* store the path to conf file for populating other srv structs as well */
128976404edcSAsim Jamshed 			conf_file = strdup(optarg);
129076404edcSAsim Jamshed 			if (NULL == conf_file) {
129176404edcSAsim Jamshed 				fprintf(stderr, "Can't duplicate conf_file string\n");
129276404edcSAsim Jamshed 				return EXIT_FAILURE;
129376404edcSAsim Jamshed 			}
129476404edcSAsim Jamshed #endif
129576404edcSAsim Jamshed 			if (config_read(srv, optarg)) {
129676404edcSAsim Jamshed 				server_free(srv);
129776404edcSAsim Jamshed 				return EXIT_FAILURE;
129876404edcSAsim Jamshed 			}
129976404edcSAsim Jamshed 			break;
130076404edcSAsim Jamshed 		case 'm':
130176404edcSAsim Jamshed 			buffer_copy_string(srv->srvconf.modules_dir, optarg);
130276404edcSAsim Jamshed 			break;
130376404edcSAsim Jamshed 		case 'n':
130476404edcSAsim Jamshed #ifdef MULTI_THREADED
130576404edcSAsim Jamshed 			cpus = get_num_cpus(optarg);
130676404edcSAsim Jamshed #else
130776404edcSAsim Jamshed 			fprintf(stderr, "-n option only works with MTCP/MULTI_THREADED support!\n");
130876404edcSAsim Jamshed 			exit(EXIT_FAILURE);
130976404edcSAsim Jamshed #endif
131076404edcSAsim Jamshed 			break;
131176404edcSAsim Jamshed 		case 'p': print_config = 1; break;
131276404edcSAsim Jamshed 		case 't': test_config = 1; break;
131376404edcSAsim Jamshed 		case 'D':
131476404edcSAsim Jamshed 			srv->srvconf.dont_daemonize = 1; break;
131576404edcSAsim Jamshed 		case 'v': show_version(); return EXIT_SUCCESS;
131676404edcSAsim Jamshed 		case 'V': show_features(); return EXIT_SUCCESS;
131776404edcSAsim Jamshed 		case 'h': show_help(); return EXIT_SUCCESS;
131876404edcSAsim Jamshed 		default:
131976404edcSAsim Jamshed 			show_help();
132076404edcSAsim Jamshed 			server_free(srv);
132176404edcSAsim Jamshed 
132276404edcSAsim Jamshed 			return EXIT_FAILURE;
132376404edcSAsim Jamshed 		}
132476404edcSAsim Jamshed 	}
132576404edcSAsim Jamshed 
132676404edcSAsim Jamshed 	if (!srv->config_storage) {
132776404edcSAsim Jamshed 		log_error_write(srv, __FILE__, __LINE__, "s",
132876404edcSAsim Jamshed 				"No configuration available. Try using -f option.");
132976404edcSAsim Jamshed 
133076404edcSAsim Jamshed 		server_free(srv);
133176404edcSAsim Jamshed 		return EXIT_FAILURE;
133276404edcSAsim Jamshed 	}
133376404edcSAsim Jamshed 
133476404edcSAsim Jamshed 	if (print_config) {
133576404edcSAsim Jamshed 		data_unset *dc = srv->config_context->data[0];
133676404edcSAsim Jamshed 		if (dc) {
133776404edcSAsim Jamshed 			dc->print(dc, 0);
133876404edcSAsim Jamshed 			fprintf(stdout, "\n");
133976404edcSAsim Jamshed 		} else {
134076404edcSAsim Jamshed 			/* shouldn't happend */
134176404edcSAsim Jamshed 			fprintf(stderr, "global config not found\n");
134276404edcSAsim Jamshed 		}
134376404edcSAsim Jamshed 	}
134476404edcSAsim Jamshed 
134576404edcSAsim Jamshed 	if (test_config) {
134676404edcSAsim Jamshed 		printf("Syntax OK\n");
134776404edcSAsim Jamshed 	}
134876404edcSAsim Jamshed 
134976404edcSAsim Jamshed 	if (test_config || print_config) {
135076404edcSAsim Jamshed 		server_free(srv);
135176404edcSAsim Jamshed 		return EXIT_SUCCESS;
135276404edcSAsim Jamshed 	}
135376404edcSAsim Jamshed 
135476404edcSAsim Jamshed 	/* close stdin and stdout, as they are not needed */
135576404edcSAsim Jamshed 	openDevNull(STDIN_FILENO);
135676404edcSAsim Jamshed 	openDevNull(STDOUT_FILENO);
135776404edcSAsim Jamshed 
135876404edcSAsim Jamshed 	if (0 != config_set_defaults(srv)) {
135976404edcSAsim Jamshed 		log_error_write(srv, __FILE__, __LINE__, "s",
136076404edcSAsim Jamshed 				"setting default values failed");
136176404edcSAsim Jamshed 		server_free(srv);
136276404edcSAsim Jamshed 		return EXIT_FAILURE;
136376404edcSAsim Jamshed 	}
136476404edcSAsim Jamshed 
136576404edcSAsim Jamshed 	/* UID handling */
136676404edcSAsim Jamshed #ifdef HAVE_GETUID
136776404edcSAsim Jamshed 	if (!i_am_root && issetugid()) {
136876404edcSAsim Jamshed 		/* we are setuid-root */
136976404edcSAsim Jamshed 
137076404edcSAsim Jamshed 		log_error_write(srv, __FILE__, __LINE__, "s",
137176404edcSAsim Jamshed 				"Are you nuts ? Don't apply a SUID bit to this binary");
137276404edcSAsim Jamshed 
137376404edcSAsim Jamshed 		server_free(srv);
137476404edcSAsim Jamshed 		return EXIT_FAILURE;
137576404edcSAsim Jamshed 	}
137676404edcSAsim Jamshed #endif
137776404edcSAsim Jamshed 
137876404edcSAsim Jamshed 	/* check document-root */
137976404edcSAsim Jamshed 	if (srv->config_storage[0]->document_root->used <= 1) {
138076404edcSAsim Jamshed 		log_error_write(srv, __FILE__, __LINE__, "s",
138176404edcSAsim Jamshed 				"document-root is not set\n");
138276404edcSAsim Jamshed 
138376404edcSAsim Jamshed 		server_free(srv);
138476404edcSAsim Jamshed 
138576404edcSAsim Jamshed 		return EXIT_FAILURE;
138676404edcSAsim Jamshed 	}
138776404edcSAsim Jamshed 
138876404edcSAsim Jamshed 	if (plugins_load(srv)) {
138976404edcSAsim Jamshed 		log_error_write(srv, __FILE__, __LINE__, "s",
139076404edcSAsim Jamshed 				"loading plugins finally failed");
139176404edcSAsim Jamshed 
139276404edcSAsim Jamshed 		plugins_free(srv);
139376404edcSAsim Jamshed 		server_free(srv);
139476404edcSAsim Jamshed 
139576404edcSAsim Jamshed 		return EXIT_FAILURE;
139676404edcSAsim Jamshed 	}
139776404edcSAsim Jamshed 
139876404edcSAsim Jamshed 	/* open pid file BEFORE chroot */
139976404edcSAsim Jamshed 	if (srv->srvconf.pid_file->used) {
140076404edcSAsim Jamshed 		if (-1 == (pid_fd = open(srv->srvconf.pid_file->ptr, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) {
140176404edcSAsim Jamshed 			struct stat st;
140276404edcSAsim Jamshed 			if (errno != EEXIST) {
140376404edcSAsim Jamshed 				log_error_write(srv, __FILE__, __LINE__, "sbs",
140476404edcSAsim Jamshed 					"opening pid-file failed:", srv->srvconf.pid_file, strerror(errno));
140576404edcSAsim Jamshed 				return EXIT_FAILURE;
140676404edcSAsim Jamshed 			}
140776404edcSAsim Jamshed 
140876404edcSAsim Jamshed 			if (0 != stat(srv->srvconf.pid_file->ptr, &st)) {
140976404edcSAsim Jamshed 				log_error_write(srv, __FILE__, __LINE__, "sbs",
141076404edcSAsim Jamshed 						"stating existing pid-file failed:", srv->srvconf.pid_file, strerror(errno));
141176404edcSAsim Jamshed 			}
141276404edcSAsim Jamshed 
141376404edcSAsim Jamshed 			if (!S_ISREG(st.st_mode)) {
141476404edcSAsim Jamshed 				log_error_write(srv, __FILE__, __LINE__, "sb",
141576404edcSAsim Jamshed 						"pid-file exists and isn't regular file:", srv->srvconf.pid_file);
141676404edcSAsim Jamshed 				return EXIT_FAILURE;
141776404edcSAsim Jamshed 			}
141876404edcSAsim Jamshed 
141976404edcSAsim Jamshed 			if (-1 == (pid_fd = open(srv->srvconf.pid_file->ptr, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) {
142076404edcSAsim Jamshed 				log_error_write(srv, __FILE__, __LINE__, "sbs",
142176404edcSAsim Jamshed 						"opening pid-file failed:", srv->srvconf.pid_file, strerror(errno));
142276404edcSAsim Jamshed 				return EXIT_FAILURE;
142376404edcSAsim Jamshed 			}
142476404edcSAsim Jamshed 		}
142576404edcSAsim Jamshed 	}
142676404edcSAsim Jamshed 
142776404edcSAsim Jamshed 	if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
142876404edcSAsim Jamshed 		/* select limits itself
142976404edcSAsim Jamshed 		 *
143076404edcSAsim Jamshed 		 * as it is a hard limit and will lead to a segfault we add some safety
143176404edcSAsim Jamshed 		 * */
143276404edcSAsim Jamshed 		srv->max_fds = FD_SETSIZE - 200;
143376404edcSAsim Jamshed 	} else {
143476404edcSAsim Jamshed 		srv->max_fds = 4096;
143576404edcSAsim Jamshed 	}
143676404edcSAsim Jamshed 
143776404edcSAsim Jamshed 	if (i_am_root) {
143876404edcSAsim Jamshed 		int use_rlimit = 1;
143976404edcSAsim Jamshed 
144076404edcSAsim Jamshed #ifdef HAVE_VALGRIND_VALGRIND_H
144176404edcSAsim Jamshed 		if (RUNNING_ON_VALGRIND) use_rlimit = 0;
144276404edcSAsim Jamshed #endif
144376404edcSAsim Jamshed 
144476404edcSAsim Jamshed #ifdef HAVE_GETRLIMIT
144576404edcSAsim Jamshed 		if (0 != getrlimit(RLIMIT_NOFILE, &rlim)) {
144676404edcSAsim Jamshed 			log_error_write(srv, __FILE__, __LINE__,
144776404edcSAsim Jamshed 					"ss", "couldn't get 'max filedescriptors'",
144876404edcSAsim Jamshed 					strerror(errno));
144976404edcSAsim Jamshed 			return EXIT_FAILURE;
145076404edcSAsim Jamshed 		}
145176404edcSAsim Jamshed 
145276404edcSAsim Jamshed 		if (use_rlimit && srv->srvconf.max_fds) {
145376404edcSAsim Jamshed 			/* set rlimits */
145476404edcSAsim Jamshed 
145576404edcSAsim Jamshed 			rlim.rlim_cur = srv->srvconf.max_fds;
145676404edcSAsim Jamshed 			rlim.rlim_max = srv->srvconf.max_fds;
145776404edcSAsim Jamshed 
145876404edcSAsim Jamshed 			if (0 != setrlimit(RLIMIT_NOFILE, &rlim)) {
145976404edcSAsim Jamshed 				log_error_write(srv, __FILE__, __LINE__,
146076404edcSAsim Jamshed 						"ss", "couldn't set 'max filedescriptors'",
146176404edcSAsim Jamshed 						strerror(errno));
146276404edcSAsim Jamshed 				return EXIT_FAILURE;
146376404edcSAsim Jamshed 			}
146476404edcSAsim Jamshed 		}
146576404edcSAsim Jamshed 
146676404edcSAsim Jamshed 		if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
146776404edcSAsim Jamshed 			srv->max_fds = rlim.rlim_cur < ((int)FD_SETSIZE) - 200 ? rlim.rlim_cur : FD_SETSIZE - 200;
146876404edcSAsim Jamshed 		} else {
146976404edcSAsim Jamshed 			srv->max_fds = rlim.rlim_cur;
147076404edcSAsim Jamshed 		}
147176404edcSAsim Jamshed 
147276404edcSAsim Jamshed 		/* set core file rlimit, if enable_cores is set */
147376404edcSAsim Jamshed 		if (use_rlimit && srv->srvconf.enable_cores && getrlimit(RLIMIT_CORE, &rlim) == 0) {
147476404edcSAsim Jamshed 			rlim.rlim_cur = rlim.rlim_max;
147576404edcSAsim Jamshed 			setrlimit(RLIMIT_CORE, &rlim);
147676404edcSAsim Jamshed 		}
147776404edcSAsim Jamshed #endif
147876404edcSAsim Jamshed 		if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
147976404edcSAsim Jamshed 			/* don't raise the limit above FD_SET_SIZE */
148076404edcSAsim Jamshed 			if (srv->max_fds > ((int)FD_SETSIZE) - 200) {
148176404edcSAsim Jamshed 				log_error_write(srv, __FILE__, __LINE__, "sd",
148276404edcSAsim Jamshed 						"can't raise max filedescriptors above",  FD_SETSIZE - 200,
148376404edcSAsim Jamshed 						"if event-handler is 'select'. Use 'poll' or something else or reduce server.max-fds.");
148476404edcSAsim Jamshed 				return EXIT_FAILURE;
148576404edcSAsim Jamshed 			}
148676404edcSAsim Jamshed 		}
148776404edcSAsim Jamshed 
148876404edcSAsim Jamshed 
148976404edcSAsim Jamshed #ifdef HAVE_PWD_H
149076404edcSAsim Jamshed 		/* set user and group */
149176404edcSAsim Jamshed 		if (srv->srvconf.username->used) {
149276404edcSAsim Jamshed 			if (NULL == (pwd = getpwnam(srv->srvconf.username->ptr))) {
149376404edcSAsim Jamshed 				log_error_write(srv, __FILE__, __LINE__, "sb",
149476404edcSAsim Jamshed 						"can't find username", srv->srvconf.username);
149576404edcSAsim Jamshed 				return EXIT_FAILURE;
149676404edcSAsim Jamshed 			}
149776404edcSAsim Jamshed 
149876404edcSAsim Jamshed 			if (pwd->pw_uid == 0) {
149976404edcSAsim Jamshed 				log_error_write(srv, __FILE__, __LINE__, "s",
150076404edcSAsim Jamshed 						"I will not set uid to 0\n");
150176404edcSAsim Jamshed 				return EXIT_FAILURE;
150276404edcSAsim Jamshed 			}
150376404edcSAsim Jamshed 		}
150476404edcSAsim Jamshed 
150576404edcSAsim Jamshed 		if (srv->srvconf.groupname->used) {
150676404edcSAsim Jamshed 			if (NULL == (grp = getgrnam(srv->srvconf.groupname->ptr))) {
150776404edcSAsim Jamshed 				log_error_write(srv, __FILE__, __LINE__, "sb",
150876404edcSAsim Jamshed 					"can't find groupname", srv->srvconf.groupname);
150976404edcSAsim Jamshed 				return EXIT_FAILURE;
151076404edcSAsim Jamshed 			}
151176404edcSAsim Jamshed 			if (grp->gr_gid == 0) {
151276404edcSAsim Jamshed 				log_error_write(srv, __FILE__, __LINE__, "s",
151376404edcSAsim Jamshed 						"I will not set gid to 0\n");
151476404edcSAsim Jamshed 				return EXIT_FAILURE;
151576404edcSAsim Jamshed 			}
151676404edcSAsim Jamshed 		}
151776404edcSAsim Jamshed #endif
151876404edcSAsim Jamshed 	} else {
151976404edcSAsim Jamshed 
152076404edcSAsim Jamshed #ifdef HAVE_GETRLIMIT
152176404edcSAsim Jamshed 		if (0 != getrlimit(RLIMIT_NOFILE, &rlim)) {
152276404edcSAsim Jamshed 			log_error_write(srv, __FILE__, __LINE__,
152376404edcSAsim Jamshed 					"ss", "couldn't get 'max filedescriptors'",
152476404edcSAsim Jamshed 					strerror(errno));
152576404edcSAsim Jamshed 			return EXIT_FAILURE;
152676404edcSAsim Jamshed 		}
152776404edcSAsim Jamshed 
152876404edcSAsim Jamshed 		/**
152976404edcSAsim Jamshed 		 * we are not root can can't increase the fd-limit, but we can reduce it
153076404edcSAsim Jamshed 		 */
153176404edcSAsim Jamshed 		if (srv->srvconf.max_fds && srv->srvconf.max_fds < (int)rlim.rlim_cur) {
153276404edcSAsim Jamshed 			/* set rlimits */
153376404edcSAsim Jamshed 
153476404edcSAsim Jamshed 			rlim.rlim_cur = srv->srvconf.max_fds;
153576404edcSAsim Jamshed 
153676404edcSAsim Jamshed 			if (0 != setrlimit(RLIMIT_NOFILE, &rlim)) {
153776404edcSAsim Jamshed 				log_error_write(srv, __FILE__, __LINE__,
153876404edcSAsim Jamshed 						"ss", "couldn't set 'max filedescriptors'",
153976404edcSAsim Jamshed 						strerror(errno));
154076404edcSAsim Jamshed 				return EXIT_FAILURE;
154176404edcSAsim Jamshed 			}
154276404edcSAsim Jamshed 		}
154376404edcSAsim Jamshed 
154476404edcSAsim Jamshed 		if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
154576404edcSAsim Jamshed 			srv->max_fds = rlim.rlim_cur < ((int)FD_SETSIZE) - 200 ? rlim.rlim_cur : FD_SETSIZE - 200;
154676404edcSAsim Jamshed 		} else {
154776404edcSAsim Jamshed 			srv->max_fds = rlim.rlim_cur;
154876404edcSAsim Jamshed 		}
154976404edcSAsim Jamshed 
155076404edcSAsim Jamshed 		/* set core file rlimit, if enable_cores is set */
155176404edcSAsim Jamshed 		if (srv->srvconf.enable_cores && getrlimit(RLIMIT_CORE, &rlim) == 0) {
155276404edcSAsim Jamshed 			rlim.rlim_cur = rlim.rlim_max;
155376404edcSAsim Jamshed 			setrlimit(RLIMIT_CORE, &rlim);
155476404edcSAsim Jamshed 		}
155576404edcSAsim Jamshed 
155676404edcSAsim Jamshed #endif
155776404edcSAsim Jamshed 		if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
155876404edcSAsim Jamshed 			/* don't raise the limit above FD_SET_SIZE */
155976404edcSAsim Jamshed 			if (srv->max_fds > ((int)FD_SETSIZE) - 200) {
156076404edcSAsim Jamshed 				log_error_write(srv, __FILE__, __LINE__, "sd",
156176404edcSAsim Jamshed 						"can't raise max filedescriptors above",  FD_SETSIZE - 200,
156276404edcSAsim Jamshed 						"if event-handler is 'select'. Use 'poll' or something else or reduce server.max-fds.");
156376404edcSAsim Jamshed 				return EXIT_FAILURE;
156476404edcSAsim Jamshed 			}
156576404edcSAsim Jamshed 		}
156676404edcSAsim Jamshed 	}
156776404edcSAsim Jamshed #ifdef MULTI_THREADED
156876404edcSAsim Jamshed 
156976404edcSAsim Jamshed #if defined HAVE_FORK
157076404edcSAsim Jamshed 	/* network is up, let's deamonize ourself */
157176404edcSAsim Jamshed 	if (srv->srvconf.dont_daemonize == 0) daemonize();
157276404edcSAsim Jamshed #endif
157376404edcSAsim Jamshed #ifdef USE_MTCP
157476404edcSAsim Jamshed 	/* set max-conns */
157576404edcSAsim Jamshed 	set_max_conns(srv, 0);
157676404edcSAsim Jamshed #else
157776404edcSAsim Jamshed 	/* set the first_entry field */
157876404edcSAsim Jamshed 	srv->first_entry = srv;
157976404edcSAsim Jamshed 
158076404edcSAsim Jamshed 	/* set max-conns */
158176404edcSAsim Jamshed 	set_max_conns(srv, 1);
158276404edcSAsim Jamshed #endif
158376404edcSAsim Jamshed 	/* thread-wide network initialization  */
158476404edcSAsim Jamshed 	/* first initialize srv_states */
158576404edcSAsim Jamshed 	init_server_states(&srv_states, cpus, srv, conf_file);
158676404edcSAsim Jamshed 
158776404edcSAsim Jamshed #ifdef USE_MTCP
158876404edcSAsim Jamshed 	/**
158976404edcSAsim Jamshed 	 * it is important that core limit is set
159076404edcSAsim Jamshed 	 * before mtcp_init() is called. You can
159176404edcSAsim Jamshed 	 * not set core_limit after mtcp_init()
159276404edcSAsim Jamshed 	 */
159376404edcSAsim Jamshed 	//	mtcp_getconf(&mcfg);
159476404edcSAsim Jamshed 	//	mcfg.num_cores = cpus;
159576404edcSAsim Jamshed 	//	mtcp_setconf(&mcfg);
159676404edcSAsim Jamshed 	/* initialize the mtcp context */
159776404edcSAsim Jamshed 	if (mtcp_init("mos.conf")) {
159876404edcSAsim Jamshed 		fprintf(stderr, "Failed to initialize mtcp\n");
159976404edcSAsim Jamshed 		goto clean_up;
160076404edcSAsim Jamshed 	}
160176404edcSAsim Jamshed 
160276404edcSAsim Jamshed 	mtcp_getconf(&mcfg);
160376404edcSAsim Jamshed 	mcfg.max_concurrency = mcfg.max_num_buffers = srv_states[0]->max_conns;
160476404edcSAsim Jamshed 	mcfg.num_cores = cpus;
160576404edcSAsim Jamshed 	mtcp_setconf(&mcfg);
160676404edcSAsim Jamshed 
160776404edcSAsim Jamshed 	/* register SIGINT signal handler */
160876404edcSAsim Jamshed 	mtcp_register_signal(SIGINT, signal_handler);
160976404edcSAsim Jamshed #endif
161076404edcSAsim Jamshed 	/* now spawn the threads and initialize the underlying networking layer */
161176404edcSAsim Jamshed 	for (i = 0; i < cpus; i++) {
161276404edcSAsim Jamshed 		if (mcfg.cpu_mask & (1L << i)) {
161376404edcSAsim Jamshed 			srv_states[i]->cpu = i;
161476404edcSAsim Jamshed #if 0
161576404edcSAsim Jamshed 			start_server((void *)srv_states[i]);
161676404edcSAsim Jamshed #endif
161776404edcSAsim Jamshed 			if (pthread_create(&srv_states[i]->running_thread, NULL,
161876404edcSAsim Jamshed 					   start_server, (void *)srv_states[i])) {
161976404edcSAsim Jamshed 				goto clean_up;
162076404edcSAsim Jamshed 			}
162176404edcSAsim Jamshed 		}
162276404edcSAsim Jamshed 	}
162376404edcSAsim Jamshed 
162476404edcSAsim Jamshed 	/*
162576404edcSAsim Jamshed 	 * ~~~ MTCP UPDATE ~~~
162676404edcSAsim Jamshed 	 * From this point onwards, the per-core `engine' running_thread does not execute
162776404edcSAsim Jamshed 	 * the following code.
162876404edcSAsim Jamshed 	 * The main thread, however, executes the remaining system-wide initialization logic
162976404edcSAsim Jamshed 	 * before it sleeps indefintely... (well... not quite... it waits till the threads
163076404edcSAsim Jamshed 	 * commit suicide)
163176404edcSAsim Jamshed 	 * ~~~ !MTCP UPDATE! ~~~
163276404edcSAsim Jamshed 	 */
163376404edcSAsim Jamshed #else
163476404edcSAsim Jamshed 	/* we need root-perms for port < 1024 */
163576404edcSAsim Jamshed 	if (0 != network_init(srv)) {
163676404edcSAsim Jamshed 		plugins_free(srv);
163776404edcSAsim Jamshed 		server_free(srv);
163876404edcSAsim Jamshed 
163976404edcSAsim Jamshed 		return EXIT_FAILURE;
164076404edcSAsim Jamshed 	}
164176404edcSAsim Jamshed #endif /* !MULTI_THREADED */
164276404edcSAsim Jamshed 
164376404edcSAsim Jamshed 	if (i_am_root) {
164476404edcSAsim Jamshed #ifdef HAVE_PWD_H
164576404edcSAsim Jamshed 		/*
164676404edcSAsim Jamshed 		 * Change group before chroot, when we have access
164776404edcSAsim Jamshed 		 * to /etc/group
164876404edcSAsim Jamshed 		 * */
164976404edcSAsim Jamshed 		if (NULL != grp) {
165076404edcSAsim Jamshed 			setgid(grp->gr_gid);
165176404edcSAsim Jamshed 			setgroups(0, NULL);
165276404edcSAsim Jamshed 			if (srv->srvconf.username->used) {
165376404edcSAsim Jamshed 				initgroups(srv->srvconf.username->ptr, grp->gr_gid);
165476404edcSAsim Jamshed 			}
165576404edcSAsim Jamshed 		}
165676404edcSAsim Jamshed #endif
165776404edcSAsim Jamshed #ifdef HAVE_CHROOT
165876404edcSAsim Jamshed 		if (srv->srvconf.changeroot->used) {
165976404edcSAsim Jamshed 			tzset();
166076404edcSAsim Jamshed 
166176404edcSAsim Jamshed 			if (-1 == chroot(srv->srvconf.changeroot->ptr)) {
166276404edcSAsim Jamshed 				log_error_write(srv, __FILE__, __LINE__, "ss", "chroot failed: ", strerror(errno));
166376404edcSAsim Jamshed 				return EXIT_FAILURE;
166476404edcSAsim Jamshed 			}
166576404edcSAsim Jamshed 			if (-1 == chdir("/")) {
166676404edcSAsim Jamshed 				log_error_write(srv, __FILE__, __LINE__, "ss", "chdir failed: ", strerror(errno));
166776404edcSAsim Jamshed 				return EXIT_FAILURE;
166876404edcSAsim Jamshed 			}
166976404edcSAsim Jamshed 		}
167076404edcSAsim Jamshed #endif
167176404edcSAsim Jamshed #ifdef HAVE_PWD_H
167276404edcSAsim Jamshed 		/* drop root privs */
167376404edcSAsim Jamshed 		if (NULL != pwd) {
167476404edcSAsim Jamshed 			setuid(pwd->pw_uid);
167576404edcSAsim Jamshed 		}
167676404edcSAsim Jamshed #endif
167776404edcSAsim Jamshed #if defined(HAVE_SYS_PRCTL_H) && defined(PR_SET_DUMPABLE)
167876404edcSAsim Jamshed 		/**
167976404edcSAsim Jamshed 		 * on IRIX 6.5.30 they have prctl() but no DUMPABLE
168076404edcSAsim Jamshed 		 */
168176404edcSAsim Jamshed 		if (srv->srvconf.enable_cores) {
168276404edcSAsim Jamshed 			prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
168376404edcSAsim Jamshed 		}
168476404edcSAsim Jamshed #endif
168576404edcSAsim Jamshed 	}
168676404edcSAsim Jamshed 
168776404edcSAsim Jamshed #ifndef MULTI_THREADED
168876404edcSAsim Jamshed 	/* set max-conns */
168976404edcSAsim Jamshed 	set_max_conns(srv, 1);
169076404edcSAsim Jamshed 	load_plugins(srv);
169176404edcSAsim Jamshed #endif
169276404edcSAsim Jamshed 
169376404edcSAsim Jamshed #ifdef HAVE_FORK
169476404edcSAsim Jamshed #ifndef MULTI_THREADED
169576404edcSAsim Jamshed 	/* network is up, let's deamonize ourself */
169676404edcSAsim Jamshed 	if (srv->srvconf.dont_daemonize == 0) daemonize();
169776404edcSAsim Jamshed #endif
169876404edcSAsim Jamshed #endif
169976404edcSAsim Jamshed 
170076404edcSAsim Jamshed 	srv->gid = getgid();
170176404edcSAsim Jamshed 	srv->uid = getuid();
170276404edcSAsim Jamshed 
170376404edcSAsim Jamshed 	/* write pid file */
170476404edcSAsim Jamshed 	if (pid_fd != -1) {
170576404edcSAsim Jamshed 		buffer_copy_long(srv->tmp_buf, getpid());
170676404edcSAsim Jamshed 		buffer_append_string_len(srv->tmp_buf, CONST_STR_LEN("\n"));
170776404edcSAsim Jamshed 		write(pid_fd, srv->tmp_buf->ptr, srv->tmp_buf->used - 1);
170876404edcSAsim Jamshed 		close(pid_fd);
170976404edcSAsim Jamshed 		pid_fd = -1;
171076404edcSAsim Jamshed 	}
171176404edcSAsim Jamshed 
171276404edcSAsim Jamshed #ifndef MULTI_THREADED
171376404edcSAsim Jamshed 	/* Close stderr ASAP in the child process to make sure that nothing
171476404edcSAsim Jamshed 	 * is being written to that fd which may not be valid anymore. */
171576404edcSAsim Jamshed 	if (-1 == log_error_open(srv)) {
171676404edcSAsim Jamshed 		log_error_write(srv, __FILE__, __LINE__, "s", "Opening errorlog failed. Going down.");
171776404edcSAsim Jamshed 
171876404edcSAsim Jamshed 		plugins_free(srv);
171976404edcSAsim Jamshed 		network_close(srv);
172076404edcSAsim Jamshed 		server_free(srv);
172176404edcSAsim Jamshed 		return EXIT_FAILURE;
172276404edcSAsim Jamshed 	}
172376404edcSAsim Jamshed 
172476404edcSAsim Jamshed 	if (HANDLER_GO_ON != plugins_call_set_defaults(srv)) {
172576404edcSAsim Jamshed 		log_error_write(srv, __FILE__, __LINE__, "s", "Configuration of plugins failed. Going down.");
172676404edcSAsim Jamshed 
172776404edcSAsim Jamshed 		plugins_free(srv);
172876404edcSAsim Jamshed 		network_close(srv);
172976404edcSAsim Jamshed 		server_free(srv);
173076404edcSAsim Jamshed 
173176404edcSAsim Jamshed 		return EXIT_FAILURE;
173276404edcSAsim Jamshed 	}
173376404edcSAsim Jamshed #endif
173476404edcSAsim Jamshed 	/* dump unused config-keys */
173576404edcSAsim Jamshed 	for (i = 0; i < srv->config_context->used; i++) {
173676404edcSAsim Jamshed 		array *config = ((data_config *)srv->config_context->data[i])->value;
173776404edcSAsim Jamshed 		size_t j;
173876404edcSAsim Jamshed 
173976404edcSAsim Jamshed 		for (j = 0; config && j < config->used; j++) {
174076404edcSAsim Jamshed 			data_unset *du = config->data[j];
174176404edcSAsim Jamshed 
174276404edcSAsim Jamshed 			/* all var.* is known as user defined variable */
174376404edcSAsim Jamshed 			if (strncmp(du->key->ptr, "var.", sizeof("var.") - 1) == 0) {
174476404edcSAsim Jamshed 				continue;
174576404edcSAsim Jamshed 			}
174676404edcSAsim Jamshed 
174776404edcSAsim Jamshed 			if (NULL == array_get_element(srv->config_touched, du->key->ptr)) {
174876404edcSAsim Jamshed 				log_error_write(srv, __FILE__, __LINE__, "sbs",
174976404edcSAsim Jamshed 						"WARNING: unknown config-key:",
175076404edcSAsim Jamshed 						du->key,
175176404edcSAsim Jamshed 						"(ignored)");
175276404edcSAsim Jamshed 			}
175376404edcSAsim Jamshed 		}
175476404edcSAsim Jamshed 	}
175576404edcSAsim Jamshed 
175676404edcSAsim Jamshed 	if (srv->config_unsupported) {
175776404edcSAsim Jamshed 		log_error_write(srv, __FILE__, __LINE__, "s",
175876404edcSAsim Jamshed 				"Configuration contains unsupported keys. Going down.");
175976404edcSAsim Jamshed 	}
176076404edcSAsim Jamshed 
176176404edcSAsim Jamshed 	if (srv->config_deprecated) {
176276404edcSAsim Jamshed 		log_error_write(srv, __FILE__, __LINE__, "s",
176376404edcSAsim Jamshed 				"Configuration contains deprecated keys. Going down.");
176476404edcSAsim Jamshed 	}
176576404edcSAsim Jamshed 
176676404edcSAsim Jamshed 	if (srv->config_unsupported || srv->config_deprecated) {
176776404edcSAsim Jamshed 		plugins_free(srv);
176876404edcSAsim Jamshed 		network_close(srv);
176976404edcSAsim Jamshed 		server_free(srv);
177076404edcSAsim Jamshed 
177176404edcSAsim Jamshed 		return EXIT_FAILURE;
177276404edcSAsim Jamshed 	}
177376404edcSAsim Jamshed 
177476404edcSAsim Jamshed #ifdef HAVE_SIGACTION
177576404edcSAsim Jamshed 	memset(&act, 0, sizeof(act));
177676404edcSAsim Jamshed 	act.sa_handler = SIG_IGN;
177776404edcSAsim Jamshed 	sigaction(SIGPIPE, &act, NULL);
177876404edcSAsim Jamshed 	sigaction(SIGUSR1, &act, NULL);
177976404edcSAsim Jamshed # if defined(SA_SIGINFO)
178076404edcSAsim Jamshed 	act.sa_sigaction = sigaction_handler;
178176404edcSAsim Jamshed 	sigemptyset(&act.sa_mask);
178276404edcSAsim Jamshed 	act.sa_flags = SA_SIGINFO;
178376404edcSAsim Jamshed # else
178476404edcSAsim Jamshed 	act.sa_handler = signal_handler;
178576404edcSAsim Jamshed 	sigemptyset(&act.sa_mask);
178676404edcSAsim Jamshed 	act.sa_flags = 0;
178776404edcSAsim Jamshed # endif
178876404edcSAsim Jamshed #ifndef USE_MTCP
178976404edcSAsim Jamshed 	sigaction(SIGINT,  &act, NULL);
179076404edcSAsim Jamshed #endif
179176404edcSAsim Jamshed 	sigaction(SIGTERM, &act, NULL);
179276404edcSAsim Jamshed 	sigaction(SIGHUP,  &act, NULL);
179376404edcSAsim Jamshed 	sigaction(SIGALRM, &act, NULL);
179476404edcSAsim Jamshed 	sigaction(SIGCHLD, &act, NULL);
179576404edcSAsim Jamshed 
179676404edcSAsim Jamshed #elif defined(HAVE_SIGNAL)
179776404edcSAsim Jamshed 	Control is not coming here
179876404edcSAsim Jamshed 	/* ignore the SIGPIPE from sendfile() */
179976404edcSAsim Jamshed 	signal(SIGPIPE, SIG_IGN);
180076404edcSAsim Jamshed 	signal(SIGUSR1, SIG_IGN);
180176404edcSAsim Jamshed 	signal(SIGALRM, signal_handler);
180276404edcSAsim Jamshed 	signal(SIGTERM, signal_handler);
180376404edcSAsim Jamshed 	signal(SIGHUP,  signal_handler);
180476404edcSAsim Jamshed 	signal(SIGCHLD,  signal_handler);
180576404edcSAsim Jamshed 	signal(SIGINT,  signal_handler);
180676404edcSAsim Jamshed #endif
180776404edcSAsim Jamshed 
180876404edcSAsim Jamshed #ifdef USE_ALARM
180976404edcSAsim Jamshed 	signal(SIGALRM, signal_handler);
181076404edcSAsim Jamshed 
181176404edcSAsim Jamshed 	/* setup periodic timer (1 second) */
181276404edcSAsim Jamshed 	if (setitimer(ITIMER_REAL, &interval, NULL)) {
181376404edcSAsim Jamshed 		log_error_write(srv, __FILE__, __LINE__, "s", "setting timer failed");
181476404edcSAsim Jamshed 		return EXIT_FAILURE;
181576404edcSAsim Jamshed 	}
181676404edcSAsim Jamshed 
181776404edcSAsim Jamshed 	getitimer(ITIMER_REAL, &interval);
181876404edcSAsim Jamshed #endif
181976404edcSAsim Jamshed 
182076404edcSAsim Jamshed #ifdef HAVE_FORK
182176404edcSAsim Jamshed 	/* MTCP/MULTI_THREADED UPDATE: num_childs is always zero here. Ignoring this entire code snippet */
182276404edcSAsim Jamshed 	/* start watcher and workers */
182376404edcSAsim Jamshed 	num_childs = srv->srvconf.max_worker;
182476404edcSAsim Jamshed 	if (num_childs > 0) {
182576404edcSAsim Jamshed 		int child = 0;
182676404edcSAsim Jamshed 		while (!child && !srv_shutdown && !graceful_shutdown) {
182776404edcSAsim Jamshed 			if (num_childs > 0) {
182876404edcSAsim Jamshed 				switch (fork()) {
182976404edcSAsim Jamshed 				case -1:
183076404edcSAsim Jamshed 					return EXIT_FAILURE;
183176404edcSAsim Jamshed 				case 0:
183276404edcSAsim Jamshed 					child = 1;
183376404edcSAsim Jamshed 					break;
183476404edcSAsim Jamshed 				default:
183576404edcSAsim Jamshed 					num_childs--;
183676404edcSAsim Jamshed 					break;
183776404edcSAsim Jamshed 				}
183876404edcSAsim Jamshed 			} else {
183976404edcSAsim Jamshed 				int status;
184076404edcSAsim Jamshed 
184176404edcSAsim Jamshed 				if (-1 != wait(&status)) {
184276404edcSAsim Jamshed 					/**
184376404edcSAsim Jamshed 					 * one of our workers went away
184476404edcSAsim Jamshed 					 */
184576404edcSAsim Jamshed 					num_childs++;
184676404edcSAsim Jamshed 				} else {
184776404edcSAsim Jamshed 					switch (errno) {
184876404edcSAsim Jamshed 					case EINTR:
184976404edcSAsim Jamshed 						/**
185076404edcSAsim Jamshed 						 * if we receive a SIGHUP we have to close our logs ourself as we don't
185176404edcSAsim Jamshed 						 * have the mainloop who can help us here
185276404edcSAsim Jamshed 						 */
185376404edcSAsim Jamshed 						if (handle_sig_hup) {
185476404edcSAsim Jamshed 							handle_sig_hup = 0;
185576404edcSAsim Jamshed 
185676404edcSAsim Jamshed 							log_error_cycle(srv);
185776404edcSAsim Jamshed 
185876404edcSAsim Jamshed 							/**
185976404edcSAsim Jamshed 							 * forward to all procs in the process-group
186076404edcSAsim Jamshed 							 *
186176404edcSAsim Jamshed 							 * we also send it ourself
186276404edcSAsim Jamshed 							 */
186376404edcSAsim Jamshed 							if (!forwarded_sig_hup) {
186476404edcSAsim Jamshed 								forwarded_sig_hup = 1;
186576404edcSAsim Jamshed 								kill(0, SIGHUP);
186676404edcSAsim Jamshed 							}
186776404edcSAsim Jamshed 						}
186876404edcSAsim Jamshed 						break;
186976404edcSAsim Jamshed 					default:
187076404edcSAsim Jamshed 						break;
187176404edcSAsim Jamshed 					}
187276404edcSAsim Jamshed 				}
187376404edcSAsim Jamshed 			}
187476404edcSAsim Jamshed 		}
187576404edcSAsim Jamshed 
187676404edcSAsim Jamshed 		/**
187776404edcSAsim Jamshed 		 * for the parent this is the exit-point
187876404edcSAsim Jamshed 		 */
187976404edcSAsim Jamshed 		if (!child) {
188076404edcSAsim Jamshed 			/**
188176404edcSAsim Jamshed 			 * kill all children too
188276404edcSAsim Jamshed 			 */
188376404edcSAsim Jamshed 			if (graceful_shutdown) {
188476404edcSAsim Jamshed 				kill(0, SIGINT);
188576404edcSAsim Jamshed 			} else if (srv_shutdown) {
188676404edcSAsim Jamshed 				kill(0, SIGTERM);
188776404edcSAsim Jamshed 			}
188876404edcSAsim Jamshed 
188976404edcSAsim Jamshed 			log_error_close(srv);
189076404edcSAsim Jamshed 			network_close(srv);
189176404edcSAsim Jamshed 			connections_free(srv);
189276404edcSAsim Jamshed 			plugins_free(srv);
189376404edcSAsim Jamshed 			server_free(srv);
189476404edcSAsim Jamshed 			return EXIT_SUCCESS;
189576404edcSAsim Jamshed 		}
189676404edcSAsim Jamshed 	}
189776404edcSAsim Jamshed #endif /* !HAVE_FORK */
189876404edcSAsim Jamshed 
189976404edcSAsim Jamshed #ifndef MULTI_THREADED
190076404edcSAsim Jamshed 	initialize_fd_framework(srv);
190176404edcSAsim Jamshed 
190276404edcSAsim Jamshed 	/* libev backend overwrites our SIGCHLD handler and calls waitpid on SIGCHLD; we want our own SIGCHLD handling. */
190376404edcSAsim Jamshed #ifdef HAVE_SIGACTION
190476404edcSAsim Jamshed 	sigaction(SIGCHLD, &act, NULL);
190576404edcSAsim Jamshed #elif defined(HAVE_SIGNAL)
190676404edcSAsim Jamshed 	signal(SIGCHLD,  signal_handler);
190776404edcSAsim Jamshed #endif
190876404edcSAsim Jamshed 
190976404edcSAsim Jamshed 	/* This part of code is only executed in the single-process, single-threaded version (non-mtcp/non-multithreaded) */
191076404edcSAsim Jamshed 	/* Under USE_MTCP settings, each individual `running_thread' executes the `main-loop' */
191176404edcSAsim Jamshed 	/* main-loop */
191276404edcSAsim Jamshed 	while (!srv_shutdown) {
191376404edcSAsim Jamshed 		int n;
191476404edcSAsim Jamshed 		size_t ndx;
191576404edcSAsim Jamshed 		time_t min_ts;
191676404edcSAsim Jamshed 
191776404edcSAsim Jamshed 		if (handle_sig_hup) {
191876404edcSAsim Jamshed 			handler_t r;
191976404edcSAsim Jamshed 
192076404edcSAsim Jamshed 			/* reset notification */
192176404edcSAsim Jamshed 			handle_sig_hup = 0;
192276404edcSAsim Jamshed 
192376404edcSAsim Jamshed 
192476404edcSAsim Jamshed 			/* cycle logfiles */
192576404edcSAsim Jamshed 
192676404edcSAsim Jamshed 			switch(r = plugins_call_handle_sighup(srv)) {
192776404edcSAsim Jamshed 			case HANDLER_GO_ON:
192876404edcSAsim Jamshed 				break;
192976404edcSAsim Jamshed 			default:
193076404edcSAsim Jamshed 				log_error_write(srv, __FILE__, __LINE__, "sd", "sighup-handler return with an error", r);
193176404edcSAsim Jamshed 				break;
193276404edcSAsim Jamshed 			}
193376404edcSAsim Jamshed 
193476404edcSAsim Jamshed 			if (-1 == log_error_cycle(srv)) {
193576404edcSAsim Jamshed 				log_error_write(srv, __FILE__, __LINE__, "s", "cycling errorlog failed, dying");
193676404edcSAsim Jamshed 
193776404edcSAsim Jamshed 				return EXIT_FAILURE;
193876404edcSAsim Jamshed 			} else {
193976404edcSAsim Jamshed #ifdef HAVE_SIGACTION
194076404edcSAsim Jamshed 				log_error_write(srv, __FILE__, __LINE__, "sdsd",
194176404edcSAsim Jamshed 					"logfiles cycled UID =",
194276404edcSAsim Jamshed 					last_sighup_info.si_uid,
194376404edcSAsim Jamshed 					"PID =",
194476404edcSAsim Jamshed 					last_sighup_info.si_pid);
194576404edcSAsim Jamshed #else
194676404edcSAsim Jamshed 				log_error_write(srv, __FILE__, __LINE__, "s",
194776404edcSAsim Jamshed 					"logfiles cycled");
194876404edcSAsim Jamshed #endif
194976404edcSAsim Jamshed 			}
195076404edcSAsim Jamshed 		}
195176404edcSAsim Jamshed 
195276404edcSAsim Jamshed 		if (handle_sig_alarm) {
195376404edcSAsim Jamshed 			/* a new second */
195476404edcSAsim Jamshed 
195576404edcSAsim Jamshed #ifdef USE_ALARM
195676404edcSAsim Jamshed 			/* reset notification */
195776404edcSAsim Jamshed 			handle_sig_alarm = 0;
195876404edcSAsim Jamshed #endif
195976404edcSAsim Jamshed 
196076404edcSAsim Jamshed 			/* get current time */
196176404edcSAsim Jamshed 			min_ts = time(NULL);
196276404edcSAsim Jamshed 
196376404edcSAsim Jamshed 			if (min_ts != srv->cur_ts) {
196476404edcSAsim Jamshed 				int cs = 0;
196576404edcSAsim Jamshed 				connections *conns = srv->conns;
196676404edcSAsim Jamshed 				handler_t r;
196776404edcSAsim Jamshed 
196876404edcSAsim Jamshed 				switch(r = plugins_call_handle_trigger(srv)) {
196976404edcSAsim Jamshed 				case HANDLER_GO_ON:
197076404edcSAsim Jamshed 					break;
197176404edcSAsim Jamshed 				case HANDLER_ERROR:
197276404edcSAsim Jamshed 					log_error_write(srv, __FILE__, __LINE__, "s", "one of the triggers failed");
197376404edcSAsim Jamshed 					break;
197476404edcSAsim Jamshed 				default:
197576404edcSAsim Jamshed 					log_error_write(srv, __FILE__, __LINE__, "d", r);
197676404edcSAsim Jamshed 					break;
197776404edcSAsim Jamshed 				}
197876404edcSAsim Jamshed 
197976404edcSAsim Jamshed 				/* trigger waitpid */
198076404edcSAsim Jamshed 				srv->cur_ts = min_ts;
198176404edcSAsim Jamshed 
198276404edcSAsim Jamshed 				/* cleanup stat-cache */
198376404edcSAsim Jamshed 				stat_cache_trigger_cleanup(srv);
198476404edcSAsim Jamshed 				/**
198576404edcSAsim Jamshed 				 * check all connections for timeouts
198676404edcSAsim Jamshed 				 *
198776404edcSAsim Jamshed 				 */
198876404edcSAsim Jamshed 				for (ndx = 0; ndx < conns->used; ndx++) {
198976404edcSAsim Jamshed 					int changed = 0;
199076404edcSAsim Jamshed 					connection *con;
199176404edcSAsim Jamshed 					int t_diff;
199276404edcSAsim Jamshed 
199376404edcSAsim Jamshed 					con = conns->ptr[ndx];
199476404edcSAsim Jamshed 
199576404edcSAsim Jamshed 					if (con->state == CON_STATE_READ ||
199676404edcSAsim Jamshed 					    con->state == CON_STATE_READ_POST) {
199776404edcSAsim Jamshed 						if (con->request_count == 1) {
199876404edcSAsim Jamshed 							if (srv->cur_ts - con->read_idle_ts > con->conf.max_read_idle) {
199976404edcSAsim Jamshed 								/* time - out */
200076404edcSAsim Jamshed #if 0
200176404edcSAsim Jamshed 								log_error_write(srv, __FILE__, __LINE__, "sd",
200276404edcSAsim Jamshed 										"connection closed - read-timeout:", con->fd);
200376404edcSAsim Jamshed #endif
200476404edcSAsim Jamshed 								connection_set_state(srv, con, CON_STATE_ERROR);
200576404edcSAsim Jamshed 								changed = 1;
200676404edcSAsim Jamshed 							}
200776404edcSAsim Jamshed 						} else {
200876404edcSAsim Jamshed 							if (srv->cur_ts - con->read_idle_ts > con->keep_alive_idle) {
200976404edcSAsim Jamshed 								/* time - out */
201076404edcSAsim Jamshed #if 0
201176404edcSAsim Jamshed 								log_error_write(srv, __FILE__, __LINE__, "sd",
201276404edcSAsim Jamshed 										"connection closed - read-timeout:", con->fd);
201376404edcSAsim Jamshed #endif
201476404edcSAsim Jamshed 								connection_set_state(srv, con, CON_STATE_ERROR);
201576404edcSAsim Jamshed 								changed = 1;
201676404edcSAsim Jamshed 							}
201776404edcSAsim Jamshed 						}
201876404edcSAsim Jamshed 					}
201976404edcSAsim Jamshed 
202076404edcSAsim Jamshed 					if ((con->state == CON_STATE_WRITE) &&
202176404edcSAsim Jamshed 					    (con->write_request_ts != 0)) {
202276404edcSAsim Jamshed #if 0
202376404edcSAsim Jamshed 						if (srv->cur_ts - con->write_request_ts > 60) {
202476404edcSAsim Jamshed 							log_error_write(srv, __FILE__, __LINE__, "sdd",
202576404edcSAsim Jamshed 									"connection closed - pre-write-request-timeout:", con->fd, srv->cur_ts - con->write_request_ts);
202676404edcSAsim Jamshed 						}
202776404edcSAsim Jamshed #endif
202876404edcSAsim Jamshed 
202976404edcSAsim Jamshed 						if (srv->cur_ts - con->write_request_ts > con->conf.max_write_idle) {
203076404edcSAsim Jamshed 							/* time - out */
203176404edcSAsim Jamshed 							if (con->conf.log_timeouts) {
203276404edcSAsim Jamshed 								log_error_write(srv, __FILE__, __LINE__, "sbsosds",
203376404edcSAsim Jamshed 									"NOTE: a request for",
203476404edcSAsim Jamshed 									con->request.uri,
203576404edcSAsim Jamshed 									"timed out after writing",
203676404edcSAsim Jamshed 									con->bytes_written,
203776404edcSAsim Jamshed 									"bytes. We waited",
203876404edcSAsim Jamshed 									(int)con->conf.max_write_idle,
203976404edcSAsim Jamshed 									"seconds. If this a problem increase server.max-write-idle");
204076404edcSAsim Jamshed 							}
204176404edcSAsim Jamshed 							connection_set_state(srv, con, CON_STATE_ERROR);
204276404edcSAsim Jamshed 							changed = 1;
204376404edcSAsim Jamshed 						}
204476404edcSAsim Jamshed 					}
204576404edcSAsim Jamshed 
204676404edcSAsim Jamshed 					if (con->state == CON_STATE_CLOSE && (srv->cur_ts - con->close_timeout_ts > HTTP_LINGER_TIMEOUT)) {
204776404edcSAsim Jamshed 						changed = 1;
204876404edcSAsim Jamshed 					}
204976404edcSAsim Jamshed 
205076404edcSAsim Jamshed 					/* we don't like div by zero */
205176404edcSAsim Jamshed 					if (0 == (t_diff = srv->cur_ts - con->connection_start)) t_diff = 1;
205276404edcSAsim Jamshed 
205376404edcSAsim Jamshed 					if (con->traffic_limit_reached &&
205476404edcSAsim Jamshed 					    (con->conf.kbytes_per_second == 0 ||
205576404edcSAsim Jamshed 					     ((con->bytes_written / t_diff) < con->conf.kbytes_per_second * 1024))) {
205676404edcSAsim Jamshed 						/* enable connection again */
205776404edcSAsim Jamshed 						con->traffic_limit_reached = 0;
205876404edcSAsim Jamshed 
205976404edcSAsim Jamshed 						changed = 1;
206076404edcSAsim Jamshed 					}
206176404edcSAsim Jamshed 
206276404edcSAsim Jamshed 					if (changed) {
206376404edcSAsim Jamshed 						connection_state_machine(srv, con);
206476404edcSAsim Jamshed 					}
206576404edcSAsim Jamshed 					con->bytes_written_cur_second = 0;
206676404edcSAsim Jamshed 					*(con->conf.global_bytes_per_second_cnt_ptr) = 0;
206776404edcSAsim Jamshed 
206876404edcSAsim Jamshed #if 0
206976404edcSAsim Jamshed 					if (cs == 0) {
207076404edcSAsim Jamshed 						fprintf(stderr, "connection-state: ");
207176404edcSAsim Jamshed 						cs = 1;
207276404edcSAsim Jamshed 					}
207376404edcSAsim Jamshed 
207476404edcSAsim Jamshed 					fprintf(stderr, "c[%d,%d]: %s ",
207576404edcSAsim Jamshed 						con->fd,
207676404edcSAsim Jamshed 						con->fcgi.fd,
207776404edcSAsim Jamshed 						connection_get_state(con->state));
207876404edcSAsim Jamshed #endif
207976404edcSAsim Jamshed 				}
208076404edcSAsim Jamshed 
208176404edcSAsim Jamshed 				if (cs == 1) fprintf(stderr, "\n");
208276404edcSAsim Jamshed 			}
208376404edcSAsim Jamshed 		}
208476404edcSAsim Jamshed 
208576404edcSAsim Jamshed 		if (srv->sockets_disabled) {
208676404edcSAsim Jamshed 			/* our server sockets are disabled, why ? */
208776404edcSAsim Jamshed 
208876404edcSAsim Jamshed 			if ((srv->cur_fds + srv->want_fds < srv->max_fds * 8 / 10) && /* we have enough unused fds */
208976404edcSAsim Jamshed 			    (srv->conns->used <= srv->max_conns * 9 / 10) &&
209076404edcSAsim Jamshed 			    (0 == graceful_shutdown)) {
209176404edcSAsim Jamshed 				for (i = 0; i < srv->srv_sockets.used; i++) {
209276404edcSAsim Jamshed 					server_socket *srv_socket = srv->srv_sockets.ptr[i];
209376404edcSAsim Jamshed 					fdevent_event_set(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd, FDEVENT_IN);
209476404edcSAsim Jamshed 				}
209576404edcSAsim Jamshed 
209676404edcSAsim Jamshed 				log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets enabled again");
209776404edcSAsim Jamshed 
209876404edcSAsim Jamshed 				srv->sockets_disabled = 0;
209976404edcSAsim Jamshed 			}
210076404edcSAsim Jamshed 		} else {
210176404edcSAsim Jamshed 			if ((srv->cur_fds + srv->want_fds > srv->max_fds * 9 / 10) || /* out of fds */
210276404edcSAsim Jamshed 			    (srv->conns->used >= srv->max_conns) || /* out of connections */
210376404edcSAsim Jamshed 			    (graceful_shutdown)) { /* graceful_shutdown */
210476404edcSAsim Jamshed 
210576404edcSAsim Jamshed 				/* disable server-fds */
210676404edcSAsim Jamshed 
210776404edcSAsim Jamshed 				for (i = 0; i < srv->srv_sockets.used; i++) {
210876404edcSAsim Jamshed 					server_socket *srv_socket = srv->srv_sockets.ptr[i];
210976404edcSAsim Jamshed 					fdevent_event_del(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd);
211076404edcSAsim Jamshed 
211176404edcSAsim Jamshed 					if (graceful_shutdown) {
211276404edcSAsim Jamshed 						/* we don't want this socket anymore,
211376404edcSAsim Jamshed 						 *
211476404edcSAsim Jamshed 						 * closing it right away will make it possible for
211576404edcSAsim Jamshed 						 * the next lighttpd to take over (graceful restart)
211676404edcSAsim Jamshed 						 *  */
211776404edcSAsim Jamshed 
211876404edcSAsim Jamshed 						fdevent_unregister(srv->ev, srv_socket->fd);
211976404edcSAsim Jamshed 						close(srv_socket->fd);
212076404edcSAsim Jamshed 						srv_socket->fd = -1;
212176404edcSAsim Jamshed 
212276404edcSAsim Jamshed 						/* network_close() will cleanup after us */
212376404edcSAsim Jamshed 
212476404edcSAsim Jamshed 						if (srv->srvconf.pid_file->used &&
212576404edcSAsim Jamshed 						    srv->srvconf.changeroot->used == 0) {
212676404edcSAsim Jamshed 							if (0 != unlink(srv->srvconf.pid_file->ptr)) {
212776404edcSAsim Jamshed 								if (errno != EACCES && errno != EPERM) {
212876404edcSAsim Jamshed 									log_error_write(srv, __FILE__, __LINE__, "sbds",
212976404edcSAsim Jamshed 											"unlink failed for:",
213076404edcSAsim Jamshed 											srv->srvconf.pid_file,
213176404edcSAsim Jamshed 											errno,
213276404edcSAsim Jamshed 											strerror(errno));
213376404edcSAsim Jamshed 								}
213476404edcSAsim Jamshed 							}
213576404edcSAsim Jamshed 						}
213676404edcSAsim Jamshed 					}
213776404edcSAsim Jamshed 				}
213876404edcSAsim Jamshed 
213976404edcSAsim Jamshed 				if (graceful_shutdown) {
214076404edcSAsim Jamshed 					log_error_write(srv, __FILE__, __LINE__, "s", "[note] graceful shutdown started");
214176404edcSAsim Jamshed 				} else if (srv->conns->used >= srv->max_conns) {
214276404edcSAsim Jamshed 					log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets disabled, connection limit reached");
214376404edcSAsim Jamshed 				} else {
214476404edcSAsim Jamshed 					log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets disabled, out-of-fds");
214576404edcSAsim Jamshed 				}
214676404edcSAsim Jamshed 
214776404edcSAsim Jamshed 				srv->sockets_disabled = 1;
214876404edcSAsim Jamshed 			}
214976404edcSAsim Jamshed 		}
215076404edcSAsim Jamshed 
215176404edcSAsim Jamshed 		if (graceful_shutdown && srv->conns->used == 0) {
215276404edcSAsim Jamshed 			/* we are in graceful shutdown phase and all connections are closed
215376404edcSAsim Jamshed 			 * we are ready to terminate without harming anyone */
215476404edcSAsim Jamshed 			srv_shutdown = 1;
215576404edcSAsim Jamshed 		}
215676404edcSAsim Jamshed 
215776404edcSAsim Jamshed 		/* we still have some fds to share */
215876404edcSAsim Jamshed 		if (srv->want_fds) {
215976404edcSAsim Jamshed 			/* check the fdwaitqueue for waiting fds */
216076404edcSAsim Jamshed 			int free_fds = srv->max_fds - srv->cur_fds - 16;
216176404edcSAsim Jamshed 			connection *con;
216276404edcSAsim Jamshed 
216376404edcSAsim Jamshed 			for (; free_fds > 0 && NULL != (con = fdwaitqueue_unshift(srv, srv->fdwaitqueue)); free_fds--) {
216476404edcSAsim Jamshed 				connection_state_machine(srv, con);
216576404edcSAsim Jamshed 
216676404edcSAsim Jamshed 				srv->want_fds--;
216776404edcSAsim Jamshed 			}
216876404edcSAsim Jamshed 		}
216976404edcSAsim Jamshed 
217076404edcSAsim Jamshed 		if ((n = fdevent_poll(srv->ev, 1000)) > 0) {
217176404edcSAsim Jamshed 			/* n is the number of events */
217276404edcSAsim Jamshed 			int revents;
217376404edcSAsim Jamshed 			int fd_ndx;
217476404edcSAsim Jamshed #if 0
217576404edcSAsim Jamshed 			if (n > 0) {
217676404edcSAsim Jamshed 				log_error_write(srv, __FILE__, __LINE__, "sd",
217776404edcSAsim Jamshed 						"polls:", n);
217876404edcSAsim Jamshed 			}
217976404edcSAsim Jamshed #endif
218076404edcSAsim Jamshed 			fd_ndx = -1;
218176404edcSAsim Jamshed 			do {
218276404edcSAsim Jamshed 				fdevent_handler handler;
218376404edcSAsim Jamshed 				void *context;
218476404edcSAsim Jamshed 				handler_t r;
218576404edcSAsim Jamshed 				int fd;
218676404edcSAsim Jamshed 
218776404edcSAsim Jamshed 				fd_ndx  = fdevent_event_next_fdndx (srv->ev, fd_ndx);
218876404edcSAsim Jamshed 				if (-1 == fd_ndx) break; /* not all fdevent handlers know how many fds got an event */
218976404edcSAsim Jamshed 
219076404edcSAsim Jamshed 				revents = fdevent_event_get_revent (srv->ev, fd_ndx);
219176404edcSAsim Jamshed 				fd      = fdevent_event_get_fd     (srv->ev, fd_ndx);
219276404edcSAsim Jamshed 				handler = fdevent_get_handler(srv->ev, fd);
219376404edcSAsim Jamshed 				context = fdevent_get_context(srv->ev, fd);
219476404edcSAsim Jamshed 
219576404edcSAsim Jamshed 				/* connection_handle_fdevent needs a joblist_append */
219676404edcSAsim Jamshed #if 0
219776404edcSAsim Jamshed 				log_error_write(srv, __FILE__, __LINE__, "sdd",
219876404edcSAsim Jamshed 						"event for", fd, revents);
219976404edcSAsim Jamshed #endif
220076404edcSAsim Jamshed 				switch (r = (*handler)(srv, context, revents)) {
220176404edcSAsim Jamshed 				case HANDLER_FINISHED:
220276404edcSAsim Jamshed 				case HANDLER_GO_ON:
220376404edcSAsim Jamshed 				case HANDLER_WAIT_FOR_EVENT:
220476404edcSAsim Jamshed 				case HANDLER_WAIT_FOR_FD:
220576404edcSAsim Jamshed 					break;
220676404edcSAsim Jamshed 				case HANDLER_ERROR:
220776404edcSAsim Jamshed 					/* should never happen */
220876404edcSAsim Jamshed 					SEGFAULT();
220976404edcSAsim Jamshed 					break;
221076404edcSAsim Jamshed 				default:
221176404edcSAsim Jamshed 					log_error_write(srv, __FILE__, __LINE__, "d", r);
221276404edcSAsim Jamshed 					break;
221376404edcSAsim Jamshed 				}
221476404edcSAsim Jamshed 			} while (--n > 0);
221576404edcSAsim Jamshed 		} else if (n < 0 && errno != EINTR) {
221676404edcSAsim Jamshed 			log_error_write(srv, __FILE__, __LINE__, "ss",
221776404edcSAsim Jamshed 					"fdevent_poll failed:",
221876404edcSAsim Jamshed 					strerror(errno));
221976404edcSAsim Jamshed 		}
222076404edcSAsim Jamshed 
222176404edcSAsim Jamshed 		for (ndx = 0; ndx < srv->joblist->used; ndx++) {
222276404edcSAsim Jamshed 			connection *con = srv->joblist->ptr[ndx];
222376404edcSAsim Jamshed 			handler_t r;
222476404edcSAsim Jamshed 
222576404edcSAsim Jamshed 			connection_state_machine(srv, con);
222676404edcSAsim Jamshed 
222776404edcSAsim Jamshed 			switch(r = plugins_call_handle_joblist(srv, con)) {
222876404edcSAsim Jamshed 			case HANDLER_FINISHED:
222976404edcSAsim Jamshed 			case HANDLER_GO_ON:
223076404edcSAsim Jamshed 				break;
223176404edcSAsim Jamshed 			default:
223276404edcSAsim Jamshed 				log_error_write(srv, __FILE__, __LINE__, "d", r);
223376404edcSAsim Jamshed 				break;
223476404edcSAsim Jamshed 			}
223576404edcSAsim Jamshed 
223676404edcSAsim Jamshed 			con->in_joblist = 0;
223776404edcSAsim Jamshed 		}
223876404edcSAsim Jamshed 
223976404edcSAsim Jamshed 		srv->joblist->used = 0;
224076404edcSAsim Jamshed 	} /* end of `while (!srv_shutdown)` */
224176404edcSAsim Jamshed 
224276404edcSAsim Jamshed #if 0
224376404edcSAsim Jamshed 	if (srv->srvconf.pid_file->used &&
224476404edcSAsim Jamshed 	    srv->srvconf.changeroot->used == 0 &&
224576404edcSAsim Jamshed 	    0 == graceful_shutdown) {
224676404edcSAsim Jamshed 		if (0 != unlink(srv->srvconf.pid_file->ptr)) {
224776404edcSAsim Jamshed 			if (errno != EACCES && errno != EPERM) {
224876404edcSAsim Jamshed 				log_error_write(srv, __FILE__, __LINE__, "sbds",
224976404edcSAsim Jamshed 						"unlink failed for:",
225076404edcSAsim Jamshed 						srv->srvconf.pid_file,
225176404edcSAsim Jamshed 						errno,
225276404edcSAsim Jamshed 						strerror(errno));
225376404edcSAsim Jamshed 			}
225476404edcSAsim Jamshed 		}
225576404edcSAsim Jamshed 	}
225676404edcSAsim Jamshed #endif
225776404edcSAsim Jamshed #ifdef HAVE_SIGACTION
225876404edcSAsim Jamshed 	log_error_write(srv, __FILE__, __LINE__, "sdsd",
225976404edcSAsim Jamshed 			"server stopped by UID =",
226076404edcSAsim Jamshed 			last_sigterm_info.si_uid,
226176404edcSAsim Jamshed 			"PID =",
226276404edcSAsim Jamshed 			last_sigterm_info.si_pid);
226376404edcSAsim Jamshed #else
226476404edcSAsim Jamshed 	log_error_write(srv, __FILE__, __LINE__, "s",
226576404edcSAsim Jamshed 			"server stopped");
226676404edcSAsim Jamshed #endif
226776404edcSAsim Jamshed #endif /* !MULTI_THREADED */
226876404edcSAsim Jamshed 
226976404edcSAsim Jamshed #ifdef MULTI_THREADED
227076404edcSAsim Jamshed 	/* main thread waits... */
227176404edcSAsim Jamshed 	for (i = 0; i < cpus; i++) {
227276404edcSAsim Jamshed 		if (mcfg.cpu_mask & (1L << i))
227376404edcSAsim Jamshed 			pthread_join(srv_states[i]->running_thread, NULL);
227476404edcSAsim Jamshed 	}
227576404edcSAsim Jamshed  clean_up:
227676404edcSAsim Jamshed #ifdef USE_MTCP
227776404edcSAsim Jamshed 	/* destroy mtcp context */
227876404edcSAsim Jamshed 	mtcp_destroy();
227976404edcSAsim Jamshed #endif
228076404edcSAsim Jamshed 	for (i = 0; i < cpus; i++) {
228176404edcSAsim Jamshed 		srv = srv_states[i];
228276404edcSAsim Jamshed #endif /* MULTI_THREADED */
228376404edcSAsim Jamshed 		/* clean-up */
228476404edcSAsim Jamshed 		log_error_close(srv);
228576404edcSAsim Jamshed 		network_close(srv);
228676404edcSAsim Jamshed 		connections_free(srv);
228776404edcSAsim Jamshed 		plugins_free(srv);
228876404edcSAsim Jamshed 		server_free(srv);
228976404edcSAsim Jamshed #ifdef MULTI_THREADED
229076404edcSAsim Jamshed 	}
229176404edcSAsim Jamshed 	free(conf_file);
229276404edcSAsim Jamshed 	free(srv_states);
229376404edcSAsim Jamshed #endif /* !MULTI_THREADED */
229476404edcSAsim Jamshed 	return EXIT_SUCCESS;
229576404edcSAsim Jamshed }
229676404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
2297