kore

Kore is a web application platform for writing scalable, concurrent web based processes in C or Python.
Commits | Files | Refs | README | LICENSE | git clone https://git.kore.io/kore.git

kore.c (20766B)



      1 /*
      2  * Copyright (c) 2013-2022 Joris Vink <joris@coders.se>
      3  *
      4  * Permission to use, copy, modify, and distribute this software for any
      5  * purpose with or without fee is hereby granted, provided that the above
      6  * copyright notice and this permission notice appear in all copies.
      7  *
      8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     15  */
     16 
     17 #include <sys/types.h>
     18 #include <sys/stat.h>
     19 #include <sys/un.h>
     20 
     21 #include <sys/socket.h>
     22 #include <sys/resource.h>
     23 
     24 #include <libgen.h>
     25 #include <fcntl.h>
     26 #include <stdio.h>
     27 #include <netdb.h>
     28 #include <signal.h>
     29 
     30 #include "kore.h"
     31 #include "hooks.h"
     32 
     33 #if !defined(KORE_NO_HTTP)
     34 #include "http.h"
     35 #endif
     36 
     37 #if defined(KORE_USE_CURL)
     38 #include "curl.h"
     39 #endif
     40 
     41 #if defined(KORE_USE_PGSQL)
     42 #include "pgsql.h"
     43 #endif
     44 
     45 #if defined(KORE_USE_PYTHON)
     46 #include "python_api.h"
     47 #endif
     48 
     49 #if defined(KORE_USE_LUA)
     50 #include "lua_api.h"
     51 #endif
     52 
     53 #if defined(KORE_USE_ACME)
     54 #include "acme.h"
     55 #endif
     56 
     57 volatile sig_atomic_t	sig_recv;
     58 struct kore_server_list	kore_servers;
     59 u_int8_t		nlisteners;
     60 int			kore_argc = 0;
     61 pid_t			kore_pid = -1;
     62 u_int16_t		cpu_count = 1;
     63 int			kore_quiet = 0;
     64 int			skip_runas = 0;
     65 int			skip_chroot = 0;
     66 u_int8_t		worker_count = 0;
     67 char			**kore_argv = NULL;
     68 int			kore_mem_guard = 0;
     69 int			kore_foreground = 1;
     70 char			*kore_progname = NULL;
     71 u_int32_t		kore_socket_backlog = 5000;
     72 int			kore_quit = KORE_QUIT_NONE;
     73 char			*kore_pidfile = KORE_PIDFILE_DEFAULT;
     74 
     75 struct kore_privsep	worker_privsep;
     76 
     77 extern char		**environ;
     78 extern char		*__progname;
     79 static size_t		proctitle_maxlen = 0;
     80 
     81 static void	usage(void);
     82 static void	version(void);
     83 
     84 static void	kore_write_kore_pid(void);
     85 static void	kore_proctitle_setup(void);
     86 static void	kore_server_shutdown(void);
     87 static void	kore_server_start(int, char *[]);
     88 static void	kore_call_parent_configure(int, char **);
     89 
     90 #if !defined(KORE_SINGLE_BINARY)
     91 static const char	*rarg0 = NULL;
     92 #endif
     93 
     94 static const char	*parent_config_hook = KORE_CONFIG_HOOK;
     95 static const char	*parent_teardown_hook = KORE_TEARDOWN_HOOK;
     96 
     97 #if defined(KORE_SINGLE_BINARY)
     98 static const char	*parent_daemonized_hook = KORE_DAEMONIZED_HOOK;
     99 #endif
    100 
    101 static void
    102 usage(void)
    103 {
    104 	if (kore_runtime_count() > 0) {
    105 		printf("Usage: %s [options] [app | script]\n", __progname);
    106 	} else {
    107 		printf("Usage: %s [options]\n", __progname);
    108 	}
    109 
    110 	printf("\n");
    111 	printf("Command-line options:\n");
    112 #if !defined(KORE_SINGLE_BINARY)
    113 	printf("\t-c\tThe configuration file to load when starting.\n");
    114 #endif
    115 	printf("\t-f\tDo not daemonize, everything runs in the foreground.\n");
    116 	printf("\t-h\tThis help text.\n");
    117 	printf("\t-n\tDo not do the chroot privsep step.\n");
    118 	printf("\t-q\tQuiet mode, only logs errors.\n");
    119 	printf("\t-r\tDo not do the privsep user swapping step.\n");
    120 	printf("\t-v\tDisplay %s build information.\n", __progname);
    121 
    122 	printf("\n");
    123 	printf("Environment options:\n");
    124 	printf("  env KORE_MEM_GUARD=1\n");
    125 	printf("      Enables memory pool guards and other protections.\n");
    126 	printf("\n");
    127 	printf("      Enabling this will include guard pages for each\n");
    128 	printf("      pool entry allocations and mark pool entries as\n");
    129 	printf("      PROT_NONE when unused.\n");
    130 	printf("\n");
    131 	printf("      This catches bugs and prevents memory vulnerabilities\n");
    132 	printf("      but with performance and memory pressure costs.\n");
    133 
    134 	printf("\n");
    135 
    136 	exit(1);
    137 }
    138 
    139 static void
    140 version(void)
    141 {
    142 	printf("%s ", kore_version);
    143 #if defined(KORE_NO_HTTP)
    144 	printf("no-http ");
    145 #endif
    146 #if defined(KORE_USE_CURL)
    147 	printf("curl-%s ", LIBCURL_VERSION);
    148 #endif
    149 #if defined(KORE_USE_PGSQL)
    150 	printf("pgsql ");
    151 #endif
    152 #if defined(KORE_USE_TASKS)
    153 	printf("tasks ");
    154 #endif
    155 #if defined(KORE_USE_PYTHON)
    156 	printf("python-%s ", PY_VERSION);
    157 #endif
    158 #if defined(KORE_USE_LUA)
    159 	printf("lua-%s.%s.%s ",
    160 	    LUA_VERSION_MAJOR, LUA_VERSION_MINOR, LUA_VERSION_RELEASE);
    161 #endif
    162 #if defined(KORE_USE_ACME)
    163 	printf("acme ");
    164 #endif
    165 #if defined(KORE_DEBUG)
    166 	printf("debug ");
    167 #endif
    168 	if (!kore_tls_supported())
    169 		printf("notls ");
    170 
    171 	printf("\n");
    172 	exit(0);
    173 }
    174 
    175 int
    176 main(int argc, char *argv[])
    177 {
    178 #if !defined(KORE_SINGLE_BINARY)
    179 	struct stat			st;
    180 #endif
    181 	struct kore_runtime_call	*rcall;
    182 
    183 	kore_argc = argc;
    184 	kore_argv = argv;
    185 
    186 #if !defined(KORE_SINGLE_BINARY)
    187 	kore_default_getopt(argc, argv);
    188 #endif
    189 
    190 	kore_mem_init();
    191 	kore_msg_init();
    192 	kore_log_init();
    193 	kore_tls_init();
    194 
    195 	kore_progname = kore_strdup(argv[0]);
    196 	kore_proctitle_setup();
    197 
    198 #if !defined(KORE_SINGLE_BINARY)
    199 	argc -= optind;
    200 	argv += optind;
    201 #endif
    202 
    203 #if !defined(KORE_SINGLE_BINARY)
    204 	if (kore_runtime_count() > 0) {
    205 		if (argc > 0) {
    206 			rarg0 = argv[0];
    207 			argc--;
    208 			argv++;
    209 		}
    210 
    211 		if (rarg0) {
    212 			if (lstat(rarg0, &st) == -1) {
    213 				if (errno == ENOENT)
    214 					rarg0 = NULL;
    215 				else
    216 					fatal("stat(%s): %s", rarg0, errno_s);
    217 			}
    218 		}
    219 	}
    220 #endif
    221 
    222 	kore_pid = getpid();
    223 	nlisteners = 0;
    224 	LIST_INIT(&kore_servers);
    225 
    226 	kore_platform_init();
    227 #if !defined(KORE_NO_HTTP)
    228 	http_parent_init();
    229 #if defined(KORE_USE_CURL)
    230 	kore_curl_sysinit();
    231 #endif
    232 #if defined(KORE_USE_PGSQL)
    233 	kore_pgsql_sys_init();
    234 #endif
    235 	kore_auth_init();
    236 	kore_validator_init();
    237 	kore_filemap_init();
    238 #endif
    239 #if defined(KORE_USE_ACME)
    240 	kore_acme_init();
    241 #endif
    242 	kore_domain_init();
    243 	kore_module_init();
    244 
    245 #if !defined(KORE_SINGLE_BINARY)
    246 	if (kore_runtime_count() == 0 && config_file == NULL)
    247 		usage();
    248 #endif
    249 	kore_module_load(NULL, NULL, KORE_MODULE_NATIVE);
    250 
    251 #if defined(KORE_USE_PYTHON)
    252 	kore_python_init();
    253 #endif
    254 
    255 #if defined(KORE_USE_LUA)
    256 	kore_lua_init();
    257 #endif
    258 
    259 #if !defined(KORE_SINGLE_BINARY)
    260 	if (kore_runtime_count() > 0 && rarg0 != NULL)
    261 		kore_runtime_resolve(rarg0, &st);
    262 #endif
    263 
    264 #if defined(KORE_SINGLE_BINARY)
    265 	kore_call_parent_configure(argc, argv);
    266 #else
    267 	if (kore_runtime_count() > 0 && rarg0 != NULL)
    268 		kore_call_parent_configure(argc, argv);
    269 #endif
    270 
    271 	kore_parse_config();
    272 
    273 #if !defined(KORE_SINGLE_BINARY)
    274 	free(config_file);
    275 #endif
    276 
    277 #if !defined(KORE_NO_HTTP)
    278 	if (http_body_disk_offload > 0) {
    279 		if (mkdir(http_body_disk_path, 0700) == -1 && errno != EEXIST) {
    280 			printf("can't create http_body_disk_path '%s': %s\n",
    281 			    http_body_disk_path, errno_s);
    282 			return (KORE_RESULT_ERROR);
    283 		}
    284 	}
    285 #endif
    286 
    287 	kore_signal_setup();
    288 	kore_server_start(argc, argv);
    289 	kore_server_shutdown();
    290 
    291 	rcall = kore_runtime_getcall(parent_teardown_hook);
    292 	if (rcall != NULL) {
    293 		kore_runtime_execute(rcall);
    294 		kore_free(rcall);
    295 	}
    296 
    297 	if (unlink(kore_pidfile) == -1 && errno != ENOENT)
    298 		kore_log(LOG_NOTICE, "failed to remove pidfile (%s)", errno_s);
    299 
    300 	kore_server_cleanup();
    301 
    302 	if (!kore_quiet)
    303 		kore_log(LOG_INFO, "goodbye");
    304 
    305 #if defined(KORE_USE_PYTHON)
    306 	kore_python_cleanup();
    307 #endif
    308 
    309 #if defined(KORE_USE_LUA)
    310 	kore_lua_cleanup();
    311 #endif
    312 
    313 	kore_mem_cleanup();
    314 
    315 	return (kore_quit);
    316 }
    317 
    318 void
    319 kore_default_getopt(int argc, char **argv)
    320 {
    321 	int		ch;
    322 
    323 #if !defined(KORE_SINGLE_BINARY)
    324 	while ((ch = getopt(argc, argv, "c:dfhnqrv")) != -1) {
    325 #else
    326 	while ((ch = getopt(argc, argv, "dfhnqrv")) != -1) {
    327 #endif
    328 		switch (ch) {
    329 #if !defined(KORE_SINGLE_BINARY)
    330 		case 'c':
    331 			free(config_file);
    332 			if ((config_file = strdup(optarg)) == NULL)
    333 				fatal("strdup");
    334 			break;
    335 #endif
    336 		case 'd':
    337 			kore_foreground = 0;
    338 			break;
    339 		case 'f':
    340 			printf("note: -f is the default now, "
    341 			    "use -d to daemonize\n");
    342 			break;
    343 		case 'h':
    344 			usage();
    345 			break;
    346 		case 'n':
    347 			skip_chroot = 1;
    348 			break;
    349 		case 'q':
    350 			kore_quiet = 1;
    351 			break;
    352 		case 'r':
    353 			skip_runas = 1;
    354 			break;
    355 		case 'v':
    356 			version();
    357 			break;
    358 		default:
    359 			usage();
    360 		}
    361 	}
    362 }
    363 
    364 int
    365 kore_server_bind(struct kore_server *srv, const char *ip, const char *port,
    366     const char *ccb)
    367 {
    368 	int			r;
    369 	struct listener		*l;
    370 	struct addrinfo		hints, *results;
    371 
    372 	memset(&hints, 0, sizeof(hints));
    373 	hints.ai_family = AF_UNSPEC;
    374 	hints.ai_socktype = SOCK_STREAM;
    375 	hints.ai_protocol = IPPROTO_TCP;
    376 	hints.ai_flags = 0;
    377 
    378 	r = getaddrinfo(ip, port, &hints, &results);
    379 	if (r != 0)
    380 		fatal("getaddrinfo(%s): %s", ip, gai_strerror(r));
    381 
    382 	l = kore_listener_create(srv);
    383 	l->host = kore_strdup(ip);
    384 	l->port = kore_strdup(port);
    385 
    386 	if (!kore_listener_init(l, results->ai_family, ccb)) {
    387 		freeaddrinfo(results);
    388 		return (KORE_RESULT_ERROR);
    389 	}
    390 
    391 	if (bind(l->fd, results->ai_addr, results->ai_addrlen) == -1) {
    392 		kore_listener_free(l);
    393 		freeaddrinfo(results);
    394 		kore_log(LOG_ERR, "bind(): %s", errno_s);
    395 		return (KORE_RESULT_ERROR);
    396 	}
    397 
    398 	freeaddrinfo(results);
    399 
    400 	if (listen(l->fd, kore_socket_backlog) == -1) {
    401 		kore_listener_free(l);
    402 		kore_log(LOG_ERR, "listen(): %s", errno_s);
    403 		return (KORE_RESULT_ERROR);
    404 	}
    405 
    406 	return (KORE_RESULT_OK);
    407 }
    408 
    409 int
    410 kore_server_bind_unix(struct kore_server *srv, const char *path,
    411     const char *ccb)
    412 {
    413 	struct listener		*l;
    414 	int			len;
    415 	struct sockaddr_un	sun;
    416 	socklen_t		socklen;
    417 
    418 	memset(&sun, 0, sizeof(sun));
    419 	sun.sun_family = AF_UNIX;
    420 
    421 	len = snprintf(sun.sun_path, sizeof(sun.sun_path), "%s", path);
    422 	if (len == -1 || (size_t)len >= sizeof(sun.sun_path)) {
    423 		kore_log(LOG_ERR, "unix socket path '%s' too long", path);
    424 		return (KORE_RESULT_ERROR);
    425 	}
    426 
    427 #if defined(__linux__)
    428 	if (sun.sun_path[0] == '@')
    429 		sun.sun_path[0] = '\0';
    430 	socklen = sizeof(sun.sun_family) + len;
    431 #else
    432 	socklen = sizeof(sun);
    433 #endif
    434 
    435 	l = kore_listener_create(srv);
    436 	l->host = kore_strdup(path);
    437 
    438 	if (!kore_listener_init(l, AF_UNIX, ccb))
    439 		return (KORE_RESULT_ERROR);
    440 
    441 	if (sun.sun_path[0] != '\0') {
    442 		if (unlink(sun.sun_path) == -1 && errno != ENOENT) {
    443 			kore_log(LOG_ERR, "unlink: %s: %s",
    444 			    sun.sun_path, errno_s);
    445 			kore_listener_free(l);
    446 			return (KORE_RESULT_ERROR);
    447 		}
    448 	}
    449 
    450 	if (bind(l->fd, (struct sockaddr *)&sun, socklen) == -1) {
    451 		kore_log(LOG_ERR, "bind: %s", errno_s);
    452 		kore_listener_free(l);
    453 		return (KORE_RESULT_ERROR);
    454 	}
    455 
    456 	if (listen(l->fd, kore_socket_backlog) == -1) {
    457 		kore_log(LOG_ERR, "listen(): %s", errno_s);
    458 		kore_listener_free(l);
    459 		return (KORE_RESULT_ERROR);
    460 	}
    461 
    462 	return (KORE_RESULT_OK);
    463 }
    464 
    465 struct kore_server *
    466 kore_server_create(const char *name)
    467 {
    468 	struct kore_server	*srv;
    469 
    470 	srv = kore_calloc(1, sizeof(struct kore_server));
    471 	srv->name = kore_strdup(name);
    472 
    473 	if (kore_tls_supported())
    474 		srv->tls = 1;
    475 	else
    476 		srv->tls = 0;
    477 
    478 	TAILQ_INIT(&srv->domains);
    479 	LIST_INIT(&srv->listeners);
    480 
    481 	LIST_INSERT_HEAD(&kore_servers, srv, list);
    482 
    483 	return (srv);
    484 }
    485 
    486 void
    487 kore_server_finalize(struct kore_server *srv)
    488 {
    489 	struct listener		*l;
    490 	const char		*proto;
    491 
    492 	if (kore_quiet)
    493 		return;
    494 
    495 	LIST_FOREACH(l, &srv->listeners, list) {
    496 		if (srv->tls)
    497 			proto = "https";
    498 		else
    499 			proto = "http";
    500 
    501 		if (l->family == AF_UNIX) {
    502 			kore_log(LOG_INFO, "%s serving %s on %s",
    503 			    srv->name, proto, l->host);
    504 		} else {
    505 			kore_log(LOG_INFO, "%s serving %s on %s:%s",
    506 			    srv->name, proto, l->host, l->port);
    507 		}
    508 	}
    509 }
    510 
    511 struct listener *
    512 kore_listener_create(struct kore_server *server)
    513 {
    514 	struct listener		*l;
    515 
    516 	l = kore_calloc(1, sizeof(struct listener));
    517 
    518 	nlisteners++;
    519 	LIST_INSERT_HEAD(&server->listeners, l, list);
    520 
    521 	l->server = server;
    522 
    523 	l->fd = -1;
    524 	l->evt.type = KORE_TYPE_LISTENER;
    525 	l->evt.handle = kore_listener_accept;
    526 
    527 	return (l);
    528 }
    529 
    530 struct kore_server *
    531 kore_server_lookup(const char *name)
    532 {
    533 	struct kore_server	*srv;
    534 
    535 	LIST_FOREACH(srv, &kore_servers, list) {
    536 		if (!strcmp(srv->name, name))
    537 			return (srv);
    538 	}
    539 
    540 	return (NULL);
    541 }
    542 
    543 int
    544 kore_listener_init(struct listener *l, int family, const char *ccb)
    545 {
    546 	switch (family) {
    547 	case AF_INET:
    548 	case AF_INET6:
    549 	case AF_UNIX:
    550 		break;
    551 	default:
    552 		fatal("unknown address family %d", family);
    553 	}
    554 
    555 	l->family = family;
    556 
    557 	if ((l->fd = socket(family, SOCK_STREAM, 0)) == -1) {
    558 		kore_listener_free(l);
    559 		kore_log(LOG_ERR, "socket(): %s", errno_s);
    560 		return (KORE_RESULT_ERROR);
    561 	}
    562 
    563 	if (fcntl(l->fd, F_SETFD, FD_CLOEXEC) == -1) {
    564 		kore_listener_free(l);
    565 		kore_log(LOG_ERR, "fcntl(): %s", errno_s);
    566 		return (KORE_RESULT_ERROR);
    567 	}
    568 
    569 	if (!kore_connection_nonblock(l->fd, family != AF_UNIX)) {
    570 		kore_listener_free(l);
    571 		kore_log(LOG_ERR, "kore_connection_nonblock(): %s", errno_s);
    572 		return (KORE_RESULT_ERROR);
    573 	}
    574 
    575 	if (!kore_sockopt(l->fd, SOL_SOCKET, SO_REUSEADDR)) {
    576 		kore_listener_free(l);
    577 		return (KORE_RESULT_ERROR);
    578 	}
    579 
    580 	if (ccb != NULL) {
    581 		if ((l->connect = kore_runtime_getcall(ccb)) == NULL) {
    582 			kore_log(LOG_ERR, "no such callback: '%s'", ccb);
    583 			kore_listener_free(l);
    584 			return (KORE_RESULT_ERROR);
    585 		}
    586 	} else {
    587 		l->connect = NULL;
    588 	}
    589 
    590 	return (KORE_RESULT_OK);
    591 }
    592 
    593 void
    594 kore_server_free(struct kore_server *srv)
    595 {
    596 	struct listener		*l;
    597 	struct kore_domain	*dom;
    598 
    599 	LIST_REMOVE(srv, list);
    600 
    601 	while ((dom = TAILQ_FIRST(&srv->domains)) != NULL)
    602 		kore_domain_free(dom);
    603 
    604 	while ((l = LIST_FIRST(&srv->listeners)) != NULL)
    605 		kore_listener_free(l);
    606 
    607 	kore_free(srv->name);
    608 	kore_free(srv);
    609 }
    610 
    611 void
    612 kore_listener_free(struct listener *l)
    613 {
    614 	int	rm;
    615 
    616 	LIST_REMOVE(l, list);
    617 
    618 	if (l->fd != -1)
    619 		close(l->fd);
    620 
    621 	rm = 0;
    622 
    623 #if defined(__linux__)
    624 	if (worker == NULL && l->family == AF_UNIX && l->host[0] != '@')
    625 		rm++;
    626 #else
    627 	if (worker == NULL && l->family == AF_UNIX)
    628 		rm++;
    629 #endif
    630 	if (rm) {
    631 		if (unlink(l->host) == -1) {
    632 			kore_log(LOG_NOTICE,
    633 			    "failed to remove unix socket %s (%s)", l->host,
    634 			    errno_s);
    635 		}
    636 	}
    637 
    638 	kore_free(l->host);
    639 	kore_free(l->port);
    640 
    641 	kore_free(l);
    642 }
    643 
    644 void
    645 kore_listener_accept(void *arg, int error)
    646 {
    647 	struct connection	*c;
    648 	struct listener		*l = arg;
    649 	u_int32_t		accepted;
    650 
    651 	if (error)
    652 		fatal("error on listening socket");
    653 
    654 	if (!(l->evt.flags & KORE_EVENT_READ))
    655 		return;
    656 
    657 	accepted = 0;
    658 
    659 	while (worker_active_connections < worker_max_connections) {
    660 		if (worker_accept_threshold != 0 &&
    661 		    accepted >= worker_accept_threshold) {
    662 			kore_worker_make_busy();
    663 			break;
    664 		}
    665 
    666 		if (!kore_connection_accept(l, &c))
    667 			break;
    668 
    669 		if (c == NULL)
    670 			break;
    671 
    672 		accepted++;
    673 		kore_platform_event_all(c->fd, c);
    674 	}
    675 }
    676 
    677 int
    678 kore_sockopt(int fd, int what, int opt)
    679 {
    680 	int		on;
    681 
    682 	on = 1;
    683 	if (setsockopt(fd, what, opt, (const char *)&on, sizeof(on)) == -1) {
    684 		kore_log(LOG_ERR, "setsockopt(): %s", errno_s);
    685 		return (KORE_RESULT_ERROR);
    686 	}
    687 
    688 	return (KORE_RESULT_OK);
    689 }
    690 
    691 void
    692 kore_signal_setup(void)
    693 {
    694 	kore_signal_trap(SIGHUP);
    695 	kore_signal_trap(SIGQUIT);
    696 	kore_signal_trap(SIGTERM);
    697 	kore_signal_trap(SIGUSR1);
    698 	kore_signal_trap(SIGCHLD);
    699 
    700 	if (kore_foreground)
    701 		kore_signal_trap(SIGINT);
    702 	else
    703 		(void)signal(SIGINT, SIG_IGN);
    704 
    705 	(void)signal(SIGPIPE, SIG_IGN);
    706 }
    707 
    708 void
    709 kore_signal_trap(int sig)
    710 {
    711 	struct sigaction	sa;
    712 
    713 	sig_recv = 0;
    714 	memset(&sa, 0, sizeof(sa));
    715 	sa.sa_handler = kore_signal;
    716 
    717 	if (sigfillset(&sa.sa_mask) == -1)
    718 		fatal("sigfillset: %s", errno_s);
    719 
    720 	if (sigaction(sig, &sa, NULL) == -1)
    721 		fatal("sigaction: %s", errno_s);
    722 }
    723 
    724 void
    725 kore_server_closeall(void)
    726 {
    727 	struct listener		*l;
    728 	struct kore_server	*srv;
    729 
    730 	LIST_FOREACH(srv, &kore_servers, list) {
    731 		LIST_FOREACH(l, &srv->listeners, list)
    732 			l->fd = -1;
    733 	}
    734 }
    735 
    736 void
    737 kore_server_cleanup(void)
    738 {
    739 	struct kore_server	*srv;
    740 
    741 	while ((srv = LIST_FIRST(&kore_servers)) != NULL)
    742 		kore_server_free(srv);
    743 }
    744 
    745 void
    746 kore_signal(int sig)
    747 {
    748 	sig_recv = sig;
    749 }
    750 
    751 void
    752 kore_shutdown(void)
    753 {
    754 	if (worker != NULL) {
    755 		kore_msg_send(KORE_MSG_PARENT, KORE_MSG_SHUTDOWN, NULL, 0);
    756 		return;
    757 	}
    758 
    759 	fatal("kore_shutdown: called from parent");
    760 }
    761 
    762 void
    763 kore_proctitle(const char *title)
    764 {
    765 	int	len;
    766 
    767 	kore_argv[1] = NULL;
    768 
    769 	len = snprintf(kore_argv[0], proctitle_maxlen, "%s %s",
    770 	    basename(kore_progname), title);
    771 	if (len == -1 || (size_t)len >= proctitle_maxlen)
    772 		fatal("proctitle '%s' too large", title);
    773 
    774 	memset(kore_argv[0] + len, 0, proctitle_maxlen - len);
    775 }
    776 
    777 void
    778 kore_hooks_set(const char *config, const char *teardown, const char *daemonized)
    779 {
    780 	parent_config_hook = config;
    781 	parent_teardown_hook = teardown;
    782 
    783 #if defined(KORE_SINGLE_BINARY)
    784 	parent_daemonized_hook = daemonized;
    785 #endif
    786 }
    787 
    788 static void
    789 kore_proctitle_setup(void)
    790 {
    791 	int		i;
    792 	char		*p;
    793 
    794 	proctitle_maxlen = 0;
    795 
    796 	for (i = 0; environ[i] != NULL; i++) {
    797 		if ((p = strdup(environ[i])) == NULL)
    798 			fatal("strdup");
    799 		proctitle_maxlen += strlen(environ[i]) + 1;
    800 		environ[i] = p;
    801 	}
    802 
    803 	for (i = 0; kore_argv[i] != NULL; i++)
    804 		proctitle_maxlen += strlen(kore_argv[i]) + 1;
    805 }
    806 
    807 static void
    808 kore_server_start(int argc, char *argv[])
    809 {
    810 	u_int32_t			tmp;
    811 	struct kore_server		*srv;
    812 	u_int64_t			netwait;
    813 	int				last_sig;
    814 #if !defined(KORE_NO_HTTP)
    815 	int				alog;
    816 	struct kore_domain		*dom;
    817 #endif
    818 #if defined(KORE_SINGLE_BINARY)
    819 	struct kore_runtime_call	*rcall;
    820 #endif
    821 
    822 	if (!kore_quiet) {
    823 		kore_log(LOG_INFO, "%s %s starting, built=%s",
    824 		    __progname, kore_version, kore_build_date);
    825 		kore_log(LOG_INFO, "memory pool protections: %s",
    826 		    kore_mem_guard ? "enabled" : "disabled");
    827 		kore_log(LOG_INFO, "built-ins: "
    828 #if defined(__linux__)
    829 		    "seccomp "
    830 #endif
    831 #if defined(KORE_USE_PGSQL)
    832 		    "pgsql "
    833 #endif
    834 #if defined(KORE_USE_TASKS)
    835 		    "tasks "
    836 #endif
    837 #if defined(KORE_USE_JSONRPC)
    838 		    "jsonrpc "
    839 #endif
    840 #if defined(KORE_USE_PYTHON)
    841 		    "python "
    842 #endif
    843 #if defined(KORE_USE_ACME)
    844 		    "acme "
    845 #endif
    846 #if defined(KORE_USE_CURL)
    847 		    "curl "
    848 #endif
    849 #if defined(KORE_USE_LUA)
    850 		    "lua "
    851 #endif
    852 		);
    853 	}
    854 
    855 	kore_tls_log_version();
    856 
    857 	if (kore_foreground == 0) {
    858 		if (daemon(1, 0) == -1)
    859 			fatal("cannot daemon(): %s", errno_s);
    860 #if defined(KORE_SINGLE_BINARY)
    861 		rcall = kore_runtime_getcall(parent_daemonized_hook);
    862 		if (rcall != NULL) {
    863 			kore_runtime_execute(rcall);
    864 			kore_free(rcall);
    865 		}
    866 #endif
    867 	}
    868 
    869 	kore_pid = getpid();
    870 	kore_write_kore_pid();
    871 
    872 #if !defined(KORE_SINGLE_BINARY)
    873 	if (kore_runtime_count() == 0 || rarg0 == NULL)
    874 		kore_call_parent_configure(argc, argv);
    875 #endif
    876 
    877 #if defined(KORE_USE_PYTHON)
    878 	kore_python_routes_resolve();
    879 #endif
    880 
    881 	/* Check if keymgr will be active. */
    882 	if (kore_tls_supported()) {
    883 		LIST_FOREACH(srv, &kore_servers, list) {
    884 			if (srv->tls) {
    885 				kore_keymgr_active = 1;
    886 				break;
    887 			}
    888 		}
    889 	} else {
    890 		kore_keymgr_active = 0;
    891 	}
    892 
    893 	kore_platform_proctitle("[parent]");
    894 
    895 	if (!kore_worker_init()) {
    896 		kore_log(LOG_ERR, "last worker log lines:");
    897 		kore_log(LOG_ERR, "=====================================");
    898 		net_init();
    899 		kore_connection_init();
    900 		kore_platform_event_init();
    901 		kore_msg_parent_init();
    902 		kore_platform_event_wait(10);
    903 		kore_worker_dispatch_signal(SIGQUIT);
    904 		kore_log(LOG_ERR, "=====================================");
    905 		return;
    906 	}
    907 
    908 	/* Set worker_max_connections for kore_connection_init(). */
    909 	tmp = worker_max_connections;
    910 	worker_max_connections = worker_count;
    911 
    912 	net_init();
    913 	kore_connection_init();
    914 	kore_platform_event_init();
    915 	kore_msg_parent_init();
    916 
    917 	worker_max_connections = tmp;
    918 
    919 	kore_timer_init();
    920 
    921 #if !defined(KORE_NO_HTTP)
    922 	alog = 0;
    923 
    924 	LIST_FOREACH(srv, &kore_servers, list) {
    925 		TAILQ_FOREACH(dom, &srv->domains, list) {
    926 			if (dom->accesslog != -1)
    927 				alog = 1;
    928 		}
    929 	}
    930 
    931 	if (alog) {
    932 		kore_timer_add(kore_accesslog_run, 100, NULL, 0);
    933 		kore_log(LOG_INFO, "accesslog vacuum is enabled");
    934 	}
    935 #endif
    936 
    937 #if defined(KORE_USE_PYTHON)
    938 	kore_msg_unregister(KORE_PYTHON_SEND_OBJ);
    939 #endif
    940 
    941 	while (kore_quit == KORE_QUIT_NONE) {
    942 		last_sig = sig_recv;
    943 
    944 		if (last_sig != 0) {
    945 			switch (last_sig) {
    946 			case SIGHUP:
    947 				kore_worker_dispatch_signal(last_sig);
    948 				kore_module_reload(0);
    949 				break;
    950 			case SIGINT:
    951 			case SIGQUIT:
    952 			case SIGTERM:
    953 				kore_quit = KORE_QUIT_NORMAL;
    954 				kore_worker_dispatch_signal(last_sig);
    955 				continue;
    956 			case SIGUSR1:
    957 				kore_worker_dispatch_signal(last_sig);
    958 				break;
    959 			case SIGCHLD:
    960 				kore_worker_reap();
    961 				break;
    962 			default:
    963 				break;
    964 			}
    965 
    966 			if (sig_recv == last_sig)
    967 				sig_recv = 0;
    968 			else
    969 				continue;
    970 		}
    971 
    972 		netwait = kore_timer_next_run(kore_time_ms());
    973 		kore_platform_event_wait(netwait);
    974 		kore_connection_prune(KORE_CONNECTION_PRUNE_DISCONNECT);
    975 		kore_timer_run(kore_time_ms());
    976 		kore_worker_reap();
    977 	}
    978 
    979 	kore_worker_dispatch_signal(SIGQUIT);
    980 }
    981 
    982 static void
    983 kore_server_shutdown(void)
    984 {
    985 	if (!kore_quiet)
    986 		kore_log(LOG_INFO, "server shutting down");
    987 
    988 	kore_worker_shutdown();
    989 
    990 #if !defined(KORE_NO_HTTP)
    991 	kore_accesslog_gather(NULL, kore_time_ms(), 1);
    992 #endif
    993 
    994 	kore_platform_event_cleanup();
    995 	kore_connection_cleanup();
    996 	kore_domain_cleanup();
    997 	kore_tls_cleanup();
    998 	net_cleanup();
    999 }
   1000 
   1001 static void
   1002 kore_write_kore_pid(void)
   1003 {
   1004 	FILE		*fp;
   1005 
   1006 	if ((fp = fopen(kore_pidfile, "w+")) == NULL) {
   1007 		printf("warning: couldn't write pid to %s (%s)\n",
   1008 		    kore_pidfile, errno_s);
   1009 	} else {
   1010 		fprintf(fp, "%d\n", kore_pid);
   1011 		fclose(fp);
   1012 	}
   1013 }
   1014 
   1015 static void
   1016 kore_call_parent_configure(int argc, char **argv)
   1017 {
   1018 	struct kore_runtime_call	*rcall;
   1019 
   1020 	rcall = kore_runtime_getcall(parent_config_hook);
   1021 	if (rcall != NULL) {
   1022 		kore_runtime_configure(rcall, argc, argv);
   1023 		kore_free(rcall);
   1024 	}
   1025 }