2017-05-25 12:01:56 +00:00
|
|
|
|
|
|
|
/*
|
2018-03-12 14:03:15 +00:00
|
|
|
* Odyssey.
|
2017-05-25 12:01:56 +00:00
|
|
|
*
|
2018-04-04 13:19:58 +00:00
|
|
|
* Scalable PostgreSQL connection pooler.
|
2017-05-25 12:01:56 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
2018-08-28 14:43:46 +00:00
|
|
|
#include <ctype.h>
|
2017-05-31 15:47:15 +00:00
|
|
|
#include <inttypes.h>
|
2018-08-28 14:43:46 +00:00
|
|
|
#include <assert.h>
|
|
|
|
|
2017-06-14 12:14:53 +00:00
|
|
|
#include <unistd.h>
|
2018-08-28 14:43:46 +00:00
|
|
|
#include <signal.h>
|
2018-07-03 13:02:46 +00:00
|
|
|
#include <sys/stat.h>
|
2017-06-20 10:40:02 +00:00
|
|
|
#include <errno.h>
|
2017-05-25 12:01:56 +00:00
|
|
|
|
|
|
|
#include <machinarium.h>
|
2018-08-28 14:43:46 +00:00
|
|
|
#include <kiwi.h>
|
|
|
|
#include <odyssey.h>
|
2017-05-25 12:01:56 +00:00
|
|
|
|
|
|
|
static inline void
|
2018-03-13 13:26:04 +00:00
|
|
|
od_system_server(void *arg)
|
2017-05-25 12:01:56 +00:00
|
|
|
{
|
2018-08-28 14:43:46 +00:00
|
|
|
od_system_server_t *server = arg;
|
2018-03-13 13:17:27 +00:00
|
|
|
od_instance_t *instance = server->global->instance;
|
2017-05-25 12:01:56 +00:00
|
|
|
|
2017-06-16 14:04:32 +00:00
|
|
|
for (;;)
|
2017-05-25 12:01:56 +00:00
|
|
|
{
|
2018-02-19 13:18:55 +00:00
|
|
|
/* accepted client io is not attached to epoll context yet */
|
2017-06-13 11:57:54 +00:00
|
|
|
machine_io_t *client_io;
|
2018-02-26 12:57:26 +00:00
|
|
|
int rc;
|
2018-03-06 15:23:52 +00:00
|
|
|
rc = machine_accept(server->io, &client_io, server->config->backlog,
|
2018-02-19 13:18:55 +00:00
|
|
|
0, UINT32_MAX);
|
2017-06-14 12:35:04 +00:00
|
|
|
if (rc == -1) {
|
2017-09-21 13:44:19 +00:00
|
|
|
od_error(&instance->logger, "server", NULL, NULL,
|
|
|
|
"accept failed: %s",
|
2018-02-26 12:57:26 +00:00
|
|
|
machine_error(server->io));
|
2017-06-20 10:40:02 +00:00
|
|
|
int errno_ = machine_errno();
|
|
|
|
if (errno_ == EADDRINUSE)
|
|
|
|
break;
|
2017-05-25 12:01:56 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2017-05-30 15:04:59 +00:00
|
|
|
/* set network options */
|
2018-03-06 15:23:52 +00:00
|
|
|
machine_set_nodelay(client_io, instance->config.nodelay);
|
|
|
|
if (instance->config.keepalive > 0)
|
|
|
|
machine_set_keepalive(client_io, 1, instance->config.keepalive);
|
2017-05-26 11:49:17 +00:00
|
|
|
|
2018-07-19 14:33:44 +00:00
|
|
|
machine_io_t *notify_io;
|
|
|
|
notify_io = machine_io_create();
|
|
|
|
if (notify_io == NULL) {
|
|
|
|
od_error(&instance->logger, "server", NULL, NULL,
|
|
|
|
"failed to allocate client io notify object");
|
|
|
|
machine_close(client_io);
|
|
|
|
machine_io_free(client_io);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
rc = machine_eventfd(notify_io);
|
|
|
|
if (rc == -1) {
|
|
|
|
od_error(&instance->logger, "server", NULL, NULL,
|
|
|
|
"failed to get eventfd for client: %s",
|
|
|
|
machine_error(client_io));
|
|
|
|
machine_close(notify_io);
|
|
|
|
machine_close(client_io);
|
|
|
|
machine_io_free(client_io);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2017-05-25 12:01:56 +00:00
|
|
|
/* allocate new client */
|
|
|
|
od_client_t *client = od_client_allocate();
|
|
|
|
if (client == NULL) {
|
2017-09-21 13:44:19 +00:00
|
|
|
od_error(&instance->logger, "server", NULL, NULL,
|
|
|
|
"failed to allocate client object");
|
2017-05-25 12:01:56 +00:00
|
|
|
machine_close(client_io);
|
|
|
|
machine_io_free(client_io);
|
|
|
|
continue;
|
|
|
|
}
|
2019-01-30 09:30:31 +00:00
|
|
|
od_id_generate(&client->id, "c");
|
2019-01-23 15:43:52 +00:00
|
|
|
rc = od_io_prepare(&client->io, client_io, instance->config.readahead);
|
|
|
|
if (rc == -1) {
|
|
|
|
od_error(&instance->logger, "server", NULL, NULL,
|
|
|
|
"failed to allocate client io object");
|
|
|
|
machine_close(client_io);
|
|
|
|
machine_io_free(client_io);
|
|
|
|
od_client_free(client);
|
|
|
|
continue;
|
|
|
|
}
|
2018-12-06 14:23:15 +00:00
|
|
|
client->rule = NULL;
|
2018-03-06 15:23:52 +00:00
|
|
|
client->config_listen = server->config;
|
2018-12-06 14:23:15 +00:00
|
|
|
client->tls = server->tls;
|
|
|
|
client->time_accept = 0;
|
2019-01-23 15:43:52 +00:00
|
|
|
client->notify_io = notify_io;
|
2018-11-27 13:19:16 +00:00
|
|
|
if (instance->config.log_session)
|
|
|
|
client->time_accept = machine_time_us();
|
2017-05-25 12:01:56 +00:00
|
|
|
|
2017-06-19 14:39:12 +00:00
|
|
|
/* create new client event and pass it to worker pool */
|
2017-06-13 11:57:54 +00:00
|
|
|
machine_msg_t *msg;
|
2018-08-28 14:43:46 +00:00
|
|
|
msg = machine_msg_create(sizeof(od_client_t*));
|
2018-12-06 14:23:15 +00:00
|
|
|
machine_msg_set_type(msg, OD_MSG_CLIENT_NEW);
|
2019-01-23 15:43:52 +00:00
|
|
|
memcpy(machine_msg_data(msg), &client, sizeof(od_client_t*));
|
2018-08-28 14:43:46 +00:00
|
|
|
|
|
|
|
od_worker_pool_t *worker_pool = server->global->worker_pool;
|
|
|
|
od_worker_pool_feed(worker_pool, msg);
|
2017-05-25 12:01:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-19 14:39:12 +00:00
|
|
|
static inline int
|
2018-08-28 14:43:46 +00:00
|
|
|
od_system_server_start(od_system_t *system, od_config_listen_t *config,
|
2017-08-29 14:43:41 +00:00
|
|
|
struct addrinfo *addr)
|
2017-06-19 14:39:12 +00:00
|
|
|
{
|
2018-12-06 14:23:15 +00:00
|
|
|
od_instance_t *instance = system->global->instance;
|
2018-08-28 14:43:46 +00:00
|
|
|
od_system_server_t *server;
|
|
|
|
server = malloc(sizeof(od_system_server_t));
|
2017-06-19 14:39:12 +00:00
|
|
|
if (server == NULL) {
|
2018-03-13 13:26:04 +00:00
|
|
|
od_error(&instance->logger, "system", NULL, NULL,
|
|
|
|
"failed to allocate system server object");
|
2017-06-19 14:39:12 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2018-03-06 15:23:52 +00:00
|
|
|
server->config = config;
|
2018-08-08 12:15:21 +00:00
|
|
|
server->addr = addr;
|
|
|
|
server->io = NULL;
|
|
|
|
server->tls = NULL;
|
2018-12-06 14:23:15 +00:00
|
|
|
server->global = system->global;
|
2018-02-26 12:57:26 +00:00
|
|
|
|
|
|
|
/* create server tls */
|
2018-12-06 14:23:15 +00:00
|
|
|
if (server->config->tls_mode != OD_CONFIG_TLS_DISABLE) {
|
2018-03-06 15:23:52 +00:00
|
|
|
server->tls = od_tls_frontend(server->config);
|
2018-02-26 12:57:26 +00:00
|
|
|
if (server->tls == NULL) {
|
|
|
|
od_error(&instance->logger, "server", NULL, NULL,
|
|
|
|
"failed to create tls handler");
|
|
|
|
free(server);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* create server io */
|
|
|
|
server->io = machine_io_create();
|
|
|
|
if (server->io == NULL) {
|
|
|
|
od_error(&instance->logger, "server", NULL, NULL,
|
2018-03-13 13:26:04 +00:00
|
|
|
"failed to create system io");
|
2018-02-26 12:57:26 +00:00
|
|
|
if (server->tls)
|
|
|
|
machine_tls_free(server->tls);
|
|
|
|
free(server);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2018-07-02 15:41:17 +00:00
|
|
|
char addr_name[PATH_MAX];
|
|
|
|
int addr_name_len;
|
|
|
|
struct sockaddr_un saddr_un;
|
|
|
|
struct sockaddr *saddr;
|
|
|
|
if (server->addr) {
|
|
|
|
/* resolve listen address and port */
|
|
|
|
od_getaddrname(server->addr, addr_name, sizeof(addr_name), 1, 1);
|
|
|
|
addr_name_len = strlen(addr_name);
|
|
|
|
saddr = server->addr->ai_addr;
|
|
|
|
} else {
|
|
|
|
/* set unix socket path */
|
|
|
|
memset(&saddr_un, 0, sizeof(saddr_un));
|
|
|
|
saddr_un.sun_family = AF_UNIX;
|
|
|
|
saddr = (struct sockaddr*)&saddr_un;
|
|
|
|
addr_name_len = od_snprintf(addr_name,
|
|
|
|
sizeof(addr_name), "%s/.s.PGSQL.%d",
|
|
|
|
instance->config.unix_socket_dir,
|
|
|
|
config->port);
|
|
|
|
strncpy(saddr_un.sun_path, addr_name, addr_name_len);
|
|
|
|
}
|
2018-02-26 12:57:26 +00:00
|
|
|
|
2018-07-02 15:41:17 +00:00
|
|
|
/* bind */
|
2018-02-26 12:57:26 +00:00
|
|
|
int rc;
|
2018-07-02 15:41:17 +00:00
|
|
|
rc = machine_bind(server->io, saddr);
|
2018-02-26 12:57:26 +00:00
|
|
|
if (rc == -1) {
|
|
|
|
od_error(&instance->logger, "server", NULL, NULL,
|
2018-07-02 15:41:17 +00:00
|
|
|
"bind to '%s' failed: %s",
|
2018-02-26 12:57:26 +00:00
|
|
|
addr_name,
|
|
|
|
machine_error(server->io));
|
|
|
|
if (server->tls)
|
|
|
|
machine_tls_free(server->tls);
|
|
|
|
machine_close(server->io);
|
|
|
|
machine_io_free(server->io);
|
|
|
|
free(server);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2018-07-03 13:02:46 +00:00
|
|
|
/* chmod */
|
|
|
|
if (server->addr == NULL) {
|
|
|
|
long mode;
|
|
|
|
mode = strtol(instance->config.unix_socket_mode, NULL, 8);
|
|
|
|
if ((errno == ERANGE && (mode == LONG_MAX || mode == LONG_MIN))) {
|
|
|
|
od_error(&instance->logger, "server", NULL, NULL,
|
|
|
|
"incorrect unix_socket_mode");
|
|
|
|
} else {
|
|
|
|
rc = chmod(saddr_un.sun_path, mode);
|
|
|
|
if (rc == -1) {
|
|
|
|
od_error(&instance->logger, "server", NULL, NULL,
|
|
|
|
"chmod(%s, %d) failed",
|
|
|
|
saddr_un.sun_path,
|
|
|
|
instance->config.unix_socket_mode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-26 12:57:26 +00:00
|
|
|
od_log(&instance->logger, "server", NULL, NULL,
|
|
|
|
"listening on %s", addr_name);
|
|
|
|
|
2017-06-19 14:39:12 +00:00
|
|
|
int64_t coroutine_id;
|
2018-03-13 13:26:04 +00:00
|
|
|
coroutine_id = machine_coroutine_create(od_system_server, server);
|
2017-06-19 14:39:12 +00:00
|
|
|
if (coroutine_id == -1) {
|
2018-03-13 13:26:04 +00:00
|
|
|
od_error(&instance->logger, "system", NULL, NULL,
|
2017-09-21 13:44:19 +00:00
|
|
|
"failed to start server coroutine");
|
2018-02-26 12:57:26 +00:00
|
|
|
if (server->tls)
|
|
|
|
machine_tls_free(server->tls);
|
|
|
|
machine_close(server->io);
|
|
|
|
machine_io_free(server->io);
|
2017-06-19 14:39:12 +00:00
|
|
|
free(server);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-02-26 12:57:26 +00:00
|
|
|
static inline int
|
2018-03-13 13:26:04 +00:00
|
|
|
od_system_listen(od_system_t *system)
|
2017-06-19 14:39:12 +00:00
|
|
|
{
|
2018-12-06 14:23:15 +00:00
|
|
|
od_instance_t *instance = system->global->instance;
|
2018-02-26 12:57:26 +00:00
|
|
|
int binded = 0;
|
2017-08-29 14:43:41 +00:00
|
|
|
od_list_t *i;
|
2018-03-06 15:23:52 +00:00
|
|
|
od_list_foreach(&instance->config.listen, i)
|
2017-08-29 14:43:41 +00:00
|
|
|
{
|
2018-08-28 14:43:46 +00:00
|
|
|
od_config_listen_t *listen;
|
|
|
|
listen = od_container_of(i, od_config_listen_t, link);
|
2017-08-29 14:43:41 +00:00
|
|
|
|
2018-07-02 15:41:17 +00:00
|
|
|
/* unix socket */
|
|
|
|
int rc;
|
|
|
|
if (listen->host == NULL) {
|
|
|
|
rc = od_system_server_start(system, listen, NULL);
|
|
|
|
if (rc == 0)
|
|
|
|
binded++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2017-08-29 14:43:41 +00:00
|
|
|
/* listen '*' */
|
|
|
|
struct addrinfo *hints_ptr = NULL;
|
|
|
|
struct addrinfo hints;
|
|
|
|
memset(&hints, 0, sizeof(struct addrinfo));
|
|
|
|
hints.ai_family = AF_UNSPEC;
|
|
|
|
hints.ai_socktype = SOCK_STREAM;
|
|
|
|
hints.ai_flags = AI_PASSIVE;
|
|
|
|
hints.ai_protocol = IPPROTO_TCP;
|
|
|
|
char *host = listen->host;
|
|
|
|
if (strcmp(listen->host, "*") == 0) {
|
|
|
|
hints_ptr = &hints;
|
|
|
|
host = NULL;
|
|
|
|
}
|
2017-06-19 14:39:12 +00:00
|
|
|
|
2017-08-29 14:43:41 +00:00
|
|
|
/* resolve listen address and port */
|
|
|
|
char port[16];
|
2017-11-27 12:54:16 +00:00
|
|
|
od_snprintf(port, sizeof(port), "%d", listen->port);
|
2017-08-29 14:43:41 +00:00
|
|
|
struct addrinfo *ai = NULL;
|
|
|
|
rc = machine_getaddrinfo(host, port, hints_ptr, &ai, UINT32_MAX);
|
|
|
|
if (rc != 0) {
|
2018-03-13 13:26:04 +00:00
|
|
|
od_error(&instance->logger, "system", NULL, NULL,
|
2017-09-21 13:44:19 +00:00
|
|
|
"failed to resolve %s:%d",
|
2017-08-29 14:43:41 +00:00
|
|
|
listen->host,
|
|
|
|
listen->port);
|
2017-08-30 13:56:13 +00:00
|
|
|
continue;
|
2017-08-29 14:43:41 +00:00
|
|
|
}
|
2017-06-19 14:39:12 +00:00
|
|
|
|
2017-08-29 14:43:41 +00:00
|
|
|
/* listen resolved addresses */
|
|
|
|
if (host) {
|
2018-03-13 13:26:04 +00:00
|
|
|
rc = od_system_server_start(system, listen, ai);
|
2018-02-26 12:57:26 +00:00
|
|
|
if (rc == 0)
|
|
|
|
binded++;
|
2017-08-30 13:56:13 +00:00
|
|
|
continue;
|
2017-08-29 14:43:41 +00:00
|
|
|
}
|
|
|
|
while (ai) {
|
2018-03-13 13:26:04 +00:00
|
|
|
rc = od_system_server_start(system, listen, ai);
|
2018-02-26 12:57:26 +00:00
|
|
|
if (rc == 0)
|
|
|
|
binded++;
|
2017-08-29 14:43:41 +00:00
|
|
|
ai = ai->ai_next;
|
|
|
|
}
|
2017-06-19 14:39:12 +00:00
|
|
|
}
|
2018-02-26 12:57:26 +00:00
|
|
|
|
|
|
|
return binded;
|
2017-06-19 14:39:12 +00:00
|
|
|
}
|
|
|
|
|
2018-07-02 15:41:17 +00:00
|
|
|
static inline void
|
|
|
|
od_system_cleanup(od_system_t *system)
|
|
|
|
{
|
2018-12-06 14:23:15 +00:00
|
|
|
od_instance_t *instance = system->global->instance;
|
2018-07-02 15:41:17 +00:00
|
|
|
|
|
|
|
od_list_t *i;
|
|
|
|
od_list_foreach(&instance->config.listen, i)
|
|
|
|
{
|
2018-08-28 14:43:46 +00:00
|
|
|
od_config_listen_t *listen;
|
|
|
|
listen = od_container_of(i, od_config_listen_t, link);
|
2018-07-02 15:41:17 +00:00
|
|
|
if (listen->host)
|
|
|
|
continue;
|
|
|
|
/* remove unix socket files */
|
|
|
|
char path[PATH_MAX];
|
|
|
|
od_snprintf(path, sizeof(path), "%s/.s.PGSQL.%d",
|
|
|
|
instance->config.unix_socket_dir,
|
|
|
|
listen->port);
|
|
|
|
unlink(path);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-18 16:22:22 +00:00
|
|
|
static inline void
|
|
|
|
od_system_config_reload(od_system_t *system)
|
|
|
|
{
|
2018-12-06 14:23:15 +00:00
|
|
|
od_instance_t *instance = system->global->instance;
|
|
|
|
od_router_t *router = system->global->router;
|
2018-09-18 16:22:22 +00:00
|
|
|
|
|
|
|
od_log(&instance->logger, "config", NULL, NULL,
|
|
|
|
"importing changes from '%s'", instance->config_file);
|
|
|
|
|
|
|
|
od_error_t error;
|
|
|
|
od_error_init(&error);
|
|
|
|
|
|
|
|
od_config_t config;
|
|
|
|
od_config_init(&config);
|
2018-12-06 14:23:15 +00:00
|
|
|
|
|
|
|
od_rules_t rules;
|
|
|
|
od_rules_init(&rules);
|
|
|
|
|
2018-09-18 16:22:22 +00:00
|
|
|
int rc;
|
2018-12-06 14:23:15 +00:00
|
|
|
rc = od_config_reader_import(&config, &rules, &error, instance->config_file);
|
2018-09-18 16:22:22 +00:00
|
|
|
if (rc == -1) {
|
|
|
|
od_error(&instance->logger, "config", NULL, NULL,
|
|
|
|
"%s", error.error);
|
|
|
|
od_config_free(&config);
|
2018-12-06 14:23:15 +00:00
|
|
|
od_rules_free(&rules);
|
2018-09-18 16:22:22 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = od_config_validate(&config, &instance->logger);
|
|
|
|
if (rc == -1) {
|
|
|
|
od_config_free(&config);
|
2018-12-06 14:23:15 +00:00
|
|
|
od_rules_free(&rules);
|
2018-09-18 16:22:22 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-12-06 14:23:15 +00:00
|
|
|
rc = od_rules_validate(&rules, &config, &instance->logger);
|
|
|
|
od_config_free(&config);
|
|
|
|
if (rc == -1) {
|
|
|
|
od_rules_free(&rules);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (instance->config.log_config)
|
|
|
|
od_rules_print(&rules, &instance->logger);
|
|
|
|
|
2018-09-18 16:22:22 +00:00
|
|
|
/* Merge configuration changes.
|
|
|
|
*
|
|
|
|
* Add new routes or obsolete previous ones which are updated or not
|
|
|
|
* present in new config file.
|
2018-12-06 14:23:15 +00:00
|
|
|
*
|
|
|
|
* Force obsolete clients to disconnect.
|
2018-09-18 16:22:22 +00:00
|
|
|
*/
|
2018-12-06 14:23:15 +00:00
|
|
|
int updates;
|
|
|
|
updates = od_router_reconfigure(router, &rules);
|
2018-09-18 16:22:22 +00:00
|
|
|
|
2018-12-06 14:23:15 +00:00
|
|
|
/* free unused rules */
|
|
|
|
od_rules_free(&rules);
|
2018-09-18 16:22:22 +00:00
|
|
|
|
2018-12-06 14:23:15 +00:00
|
|
|
od_log(&instance->logger, "rules", NULL, NULL,
|
|
|
|
"%d routes created/deleted and scheduled for removal",
|
|
|
|
updates);
|
2018-09-18 16:22:22 +00:00
|
|
|
}
|
|
|
|
|
2017-07-19 11:29:23 +00:00
|
|
|
static inline void
|
2018-03-13 13:26:04 +00:00
|
|
|
od_system_signal_handler(void *arg)
|
2017-06-14 12:14:53 +00:00
|
|
|
{
|
2018-03-13 13:26:04 +00:00
|
|
|
od_system_t *system = arg;
|
2018-12-06 14:23:15 +00:00
|
|
|
od_instance_t *instance = system->global->instance;
|
2017-06-14 12:14:53 +00:00
|
|
|
|
|
|
|
sigset_t mask;
|
|
|
|
sigemptyset(&mask);
|
|
|
|
sigaddset(&mask, SIGINT);
|
2018-02-28 14:33:38 +00:00
|
|
|
sigaddset(&mask, SIGTERM);
|
2017-07-13 11:49:44 +00:00
|
|
|
sigaddset(&mask, SIGHUP);
|
2017-06-14 12:14:53 +00:00
|
|
|
int rc;
|
|
|
|
rc = machine_signal_init(&mask);
|
|
|
|
if (rc == -1) {
|
2018-03-13 13:26:04 +00:00
|
|
|
od_error(&instance->logger, "system", NULL, NULL,
|
2017-09-21 13:44:19 +00:00
|
|
|
"failed to init signal handler");
|
2017-06-14 12:14:53 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
rc = machine_signal_wait(UINT32_MAX);
|
|
|
|
if (rc == -1)
|
|
|
|
break;
|
|
|
|
switch (rc) {
|
2018-02-28 14:33:38 +00:00
|
|
|
case SIGTERM:
|
2018-03-13 13:26:04 +00:00
|
|
|
od_log(&instance->logger, "system", NULL, NULL,
|
2018-02-28 14:33:38 +00:00
|
|
|
"SIGTERM received, shutting down");
|
2018-07-02 15:41:17 +00:00
|
|
|
od_system_cleanup(system);
|
2018-02-28 14:33:38 +00:00
|
|
|
exit(0);
|
|
|
|
break;
|
2017-06-14 12:14:53 +00:00
|
|
|
case SIGINT:
|
2018-03-13 13:26:04 +00:00
|
|
|
od_log(&instance->logger, "system", NULL, NULL,
|
2017-09-21 13:44:19 +00:00
|
|
|
"SIGINT received, shutting down");
|
2018-07-02 15:41:17 +00:00
|
|
|
od_system_cleanup(system);
|
2017-06-14 12:35:04 +00:00
|
|
|
exit(0);
|
2017-06-14 12:14:53 +00:00
|
|
|
break;
|
2017-07-13 11:49:44 +00:00
|
|
|
case SIGHUP:
|
2018-03-13 13:26:04 +00:00
|
|
|
od_log(&instance->logger, "system", NULL, NULL,
|
2018-09-18 16:22:22 +00:00
|
|
|
"SIGHUP received");
|
|
|
|
od_system_config_reload(system);
|
2017-07-13 11:49:44 +00:00
|
|
|
break;
|
2017-06-14 12:14:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-05 14:05:39 +00:00
|
|
|
static inline void
|
2018-03-13 13:26:04 +00:00
|
|
|
od_system(void *arg)
|
2017-06-05 14:05:39 +00:00
|
|
|
{
|
2018-03-13 13:26:04 +00:00
|
|
|
od_system_t *system = arg;
|
2018-12-06 14:23:15 +00:00
|
|
|
od_instance_t *instance = system->global->instance;
|
2017-06-24 14:59:28 +00:00
|
|
|
|
2018-03-02 13:12:32 +00:00
|
|
|
/* start cron coroutine */
|
2018-12-06 14:23:15 +00:00
|
|
|
od_cron_t *cron = system->global->cron;
|
|
|
|
int rc;
|
|
|
|
rc = od_cron_start(cron, system->global);
|
2017-06-05 14:05:39 +00:00
|
|
|
if (rc == -1)
|
|
|
|
return;
|
|
|
|
|
2018-02-02 11:54:13 +00:00
|
|
|
/* start worker threads */
|
2018-12-06 14:23:15 +00:00
|
|
|
od_worker_pool_t *worker_pool = system->global->worker_pool;
|
|
|
|
rc = od_worker_pool_start(worker_pool, system->global, instance->config.workers);
|
2018-02-02 11:54:13 +00:00
|
|
|
if (rc == -1)
|
|
|
|
return;
|
|
|
|
|
2018-02-02 12:50:23 +00:00
|
|
|
/* start signal handler coroutine */
|
|
|
|
int64_t coroutine_id;
|
2018-03-13 13:26:04 +00:00
|
|
|
coroutine_id = machine_coroutine_create(od_system_signal_handler, system);
|
2018-02-02 12:50:23 +00:00
|
|
|
if (coroutine_id == -1) {
|
2018-03-13 13:26:04 +00:00
|
|
|
od_error(&instance->logger, "system", NULL, NULL,
|
2018-02-02 12:50:23 +00:00
|
|
|
"failed to start signal handler");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-03-13 13:26:04 +00:00
|
|
|
/* start listen servers */
|
|
|
|
rc = od_system_listen(system);
|
2018-02-26 12:57:26 +00:00
|
|
|
if (rc == 0) {
|
2018-03-13 13:26:04 +00:00
|
|
|
od_error(&instance->logger, "system", NULL, NULL,
|
2018-02-26 12:57:26 +00:00
|
|
|
"failed to bind any listen address");
|
|
|
|
exit(1);
|
|
|
|
}
|
2017-06-05 14:05:39 +00:00
|
|
|
}
|
|
|
|
|
2018-12-06 14:23:15 +00:00
|
|
|
void
|
2018-08-28 14:43:46 +00:00
|
|
|
od_system_init(od_system_t *system)
|
2017-05-25 12:01:56 +00:00
|
|
|
{
|
2018-03-13 13:37:53 +00:00
|
|
|
system->machine = -1;
|
2018-12-06 14:23:15 +00:00
|
|
|
system->global = NULL;
|
2017-05-25 12:01:56 +00:00
|
|
|
}
|
|
|
|
|
2018-08-28 14:43:46 +00:00
|
|
|
int
|
2018-12-06 14:23:15 +00:00
|
|
|
od_system_start(od_system_t *system, od_global_t *global)
|
2017-05-25 12:01:56 +00:00
|
|
|
{
|
2018-12-06 14:23:15 +00:00
|
|
|
system->global = global;
|
|
|
|
od_instance_t *instance = global->instance;
|
2018-03-13 13:26:04 +00:00
|
|
|
system->machine = machine_create("system", od_system, system);
|
|
|
|
if (system->machine == -1) {
|
|
|
|
od_error(&instance->logger, "system", NULL, NULL,
|
|
|
|
"failed to create system thread");
|
2017-06-19 10:30:56 +00:00
|
|
|
return -1;
|
2017-05-25 12:01:56 +00:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|