diff options
author | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2020-06-10 14:55:38 +0100 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2020-06-10 14:55:38 +0100 |
commit | f6b8d1a2fec84537cba3b01331c92408246f1fc1 (patch) | |
tree | da0dc922223b1142b4cc1ea53184eea66bd755f3 /src | |
parent | dc7afbd65040bb286b369adb0e8510209accf4d2 (diff) | |
download | rspamd-f6b8d1a2fec84537cba3b01331c92408246f1fc1.tar.gz rspamd-f6b8d1a2fec84537cba3b01331c92408246f1fc1.zip |
[Rework] Close listen sockets in main after fork
Diffstat (limited to 'src')
-rw-r--r-- | src/libserver/worker_util.c | 69 |
1 files changed, 52 insertions, 17 deletions
diff --git a/src/libserver/worker_util.c b/src/libserver/worker_util.c index 4c82cb330..a5e888920 100644 --- a/src/libserver/worker_util.c +++ b/src/libserver/worker_util.c @@ -938,12 +938,12 @@ rspamd_maybe_reuseport_socket (struct rspamd_worker_listen_socket *ls) { gint nfd = -1; - if (ls->fd == -1 || ls->is_systemd) { + if (ls->is_systemd) { /* No need to reuseport */ return true; } - if (rspamd_inet_address_get_af (ls->addr) == AF_UNIX) { + if (ls->fd != -1 && rspamd_inet_address_get_af (ls->addr) == AF_UNIX) { /* Just try listen */ if (listen (ls->fd, -1) == -1) { @@ -966,7 +966,9 @@ rspamd_maybe_reuseport_socket (struct rspamd_worker_listen_socket *ls) nfd = ls->fd; } else { - close (ls->fd); + if (ls->fd != -1) { + close (ls->fd); + } ls->fd = nfd; nfd = -1; } @@ -1049,7 +1051,7 @@ rspamd_handle_child_fork (struct rspamd_worker *wrk, struct rspamd_worker_listen_socket *ls = (struct rspamd_worker_listen_socket *)cur->data; - if (close (ls->fd) == -1) { + if (ls->fd != -1 && close (ls->fd) == -1) { msg_err ("cannot close fd %d: %s", ls->fd, strerror (errno)); } @@ -1123,6 +1125,51 @@ rspamd_handle_child_fork (struct rspamd_worker *wrk, exit (EXIT_FAILURE); } +static void +rspamd_handle_main_fork (struct rspamd_worker *wrk, + struct rspamd_main *rspamd_main, + struct rspamd_worker_conf *cf, + struct ev_loop *ev_base) +{ + /* Close worker part of socketpair */ + close (wrk->control_pipe[1]); + close (wrk->srv_pipe[1]); + + rspamd_socket_nonblocking (wrk->control_pipe[0]); + rspamd_socket_nonblocking (wrk->srv_pipe[0]); + rspamd_srv_start_watching (rspamd_main, wrk, ev_base); + /* Child event */ + wrk->cld_ev.data = wrk; + ev_child_init (&wrk->cld_ev, rspamd_worker_on_term, wrk->pid, 0); + ev_child_start (rspamd_main->event_loop, &wrk->cld_ev); + /* Heartbeats */ + rspamd_main_heartbeat_start (wrk, rspamd_main->event_loop); + /* Insert worker into worker's table, pid is index */ + g_hash_table_insert (rspamd_main->workers, + GSIZE_TO_POINTER (wrk->pid), wrk); + +#if defined(SO_REUSEPORT) && defined(SO_REUSEADDR) && defined(LINUX) + /* + * Close listen sockets in the main process once a child is handling them, + * if we have reuseport + */ + GList *cur = cf->listen_socks; + + while (cur) { + struct rspamd_worker_listen_socket *ls = + (struct rspamd_worker_listen_socket *)cur->data; + + if (!ls->is_systemd && ls->fd != -1 && + rspamd_inet_address_get_af (ls->addr) != AF_UNIX) { + close (ls->fd); + ls->fd = -1; + } + + cur = g_list_next (cur); + } +#endif +} + struct rspamd_worker * rspamd_fork_worker (struct rspamd_main *rspamd_main, struct rspamd_worker_conf *cf, @@ -1185,19 +1232,7 @@ rspamd_fork_worker (struct rspamd_main *rspamd_main, rspamd_hard_terminate (rspamd_main); break; default: - /* Close worker part of socketpair */ - close (wrk->control_pipe[1]); - close (wrk->srv_pipe[1]); - rspamd_socket_nonblocking (wrk->control_pipe[0]); - rspamd_socket_nonblocking (wrk->srv_pipe[0]); - rspamd_srv_start_watching (rspamd_main, wrk, ev_base); - wrk->cld_ev.data = wrk; - ev_child_init (&wrk->cld_ev, rspamd_worker_on_term, wrk->pid, 0); - ev_child_start (rspamd_main->event_loop, &wrk->cld_ev); - rspamd_main_heartbeat_start (wrk, rspamd_main->event_loop); - /* Insert worker into worker's table, pid is index */ - g_hash_table_insert (rspamd_main->workers, - GSIZE_TO_POINTER (wrk->pid), wrk); + rspamd_handle_main_fork (wrk, rspamd_main, cf, ev_base); break; } |