commit 45f223d: [Minor] Close sockets that do not belong to a current worker

Vsevolod Stakhov vsevolod at highsecure.ru
Tue Jun 9 13:49:06 UTC 2020


Author: Vsevolod Stakhov
Date: 2020-06-09 12:55:20 +0100
URL: https://github.com/rspamd/rspamd/commit/45f223de8f3509b1cefa68cad659d373676a0841

[Minor] Close sockets that do not belong to a current worker

---
 src/libserver/worker_util.c | 202 +++++++++++++++++++++++++++-----------------
 src/libserver/worker_util.h |   3 +-
 src/rspamd.c                |  10 ++-
 3 files changed, 132 insertions(+), 83 deletions(-)

diff --git a/src/libserver/worker_util.c b/src/libserver/worker_util.c
index e0d7d6bc7..50f81fd7b 100644
--- a/src/libserver/worker_util.c
+++ b/src/libserver/worker_util.c
@@ -933,16 +933,136 @@ rspamd_main_heartbeat_start (struct rspamd_worker *wrk, struct ev_loop *event_lo
 	ev_timer_start (event_loop, &wrk->hb.heartbeat_ev);
 }
 
+/**
+ * Handles worker after fork returned zero
+ * @param wrk
+ * @param rspamd_main
+ * @param cf
+ * @param listen_sockets
+ */
+static void
+rspamd_handle_child_fork (struct rspamd_worker *wrk,
+						  struct rspamd_main *rspamd_main,
+						  struct rspamd_worker_conf *cf,
+						  GHashTable *listen_sockets)
+{
+	gint rc;
+	struct rlimit rlim;
+
+	/* Update pid for logging */
+	rspamd_log_on_fork (cf->type, rspamd_main->cfg, rspamd_main->logger);
+	wrk->pid = getpid ();
+
+	/* Init PRNG after fork */
+	rc = ottery_init (rspamd_main->cfg->libs_ctx->ottery_cfg);
+	if (rc != OTTERY_ERR_NONE) {
+		msg_err_main ("cannot initialize PRNG: %d", rc);
+		abort ();
+	}
+
+	rspamd_random_seed_fast ();
+#ifdef HAVE_EVUTIL_RNG_INIT
+	evutil_secure_rng_init ();
+#endif
+
+	/*
+	 * Libev stores all signals in a global table, so
+	 * previous handlers must be explicitly detached and forgotten
+	 * before starting a new loop
+	 */
+	ev_signal_stop (rspamd_main->event_loop, &rspamd_main->int_ev);
+	ev_signal_stop (rspamd_main->event_loop, &rspamd_main->term_ev);
+	ev_signal_stop (rspamd_main->event_loop, &rspamd_main->hup_ev);
+	ev_signal_stop (rspamd_main->event_loop, &rspamd_main->usr1_ev);
+	/* Remove the inherited event base */
+	ev_loop_destroy (rspamd_main->event_loop);
+	rspamd_main->event_loop = NULL;
+
+	/* Close unused sockets */
+	GHashTableIter it;
+	gpointer k, v;
+
+
+	g_hash_table_iter_init (&it, listen_sockets);
+
+	while (g_hash_table_iter_next (&it, &k, &v)) {
+		GList *elt = (GList *)v;
+		GList *our = cf->listen_socks;
+
+		if (our != elt) {
+			GList *cur = elt;
+
+			while (cur) {
+				struct rspamd_worker_listen_socket *ls =
+						(struct rspamd_worker_listen_socket *)cur->data;
+
+				if (close (ls->fd) == -1) {
+					msg_err ("cannot close fd %d: %s", ls->fd, strerror (errno));
+				}
+
+				cur = g_list_next (cur);
+			}
+		}
+	}
+
+	/* Drop privileges */
+	rspamd_worker_drop_priv (rspamd_main);
+	/* Set limits */
+	rspamd_worker_set_limits (rspamd_main, cf);
+	/* Re-set stack limit */
+	getrlimit (RLIMIT_STACK, &rlim);
+	rlim.rlim_cur = 100 * 1024 * 1024;
+	rlim.rlim_max = rlim.rlim_cur;
+	setrlimit (RLIMIT_STACK, &rlim);
+
+	if (cf->bind_conf) {
+		setproctitle ("%s process (%s)", cf->worker->name,
+				cf->bind_conf->bind_line);
+	}
+	else {
+		setproctitle ("%s process", cf->worker->name);
+	}
+
+	if (rspamd_main->pfh) {
+		rspamd_pidfile_close (rspamd_main->pfh);
+	}
+
+	if (rspamd_main->cfg->log_silent_workers) {
+		rspamd_log_set_log_level (rspamd_main->logger, G_LOG_LEVEL_MESSAGE);
+	}
+
+	wrk->start_time = rspamd_get_calendar_ticks ();
+
+	if (cf->bind_conf) {
+		msg_info_main ("starting %s process %P (%d); listen on: %s",
+				cf->worker->name,
+				getpid (), index, cf->bind_conf->bind_line);
+	}
+	else {
+		msg_info_main ("starting %s process %P (%d)", cf->worker->name,
+				getpid (), index);
+	}
+	/* Close parent part of socketpair */
+	close (wrk->control_pipe[0]);
+	close (wrk->srv_pipe[0]);
+	rspamd_socket_nonblocking (wrk->control_pipe[1]);
+	rspamd_socket_nonblocking (wrk->srv_pipe[1]);
+	rspamd_main->cfg->cur_worker = wrk;
+	/* Execute worker (this function should not return normally!) */
+	cf->worker->worker_start_func (wrk);
+	/* To distinguish from normal termination */
+	exit (EXIT_FAILURE);
+}
+
 struct rspamd_worker *
 rspamd_fork_worker (struct rspamd_main *rspamd_main,
 					struct rspamd_worker_conf *cf,
 					guint index,
 					struct ev_loop *ev_base,
-					rspamd_worker_term_cb term_handler)
+					rspamd_worker_term_cb term_handler,
+					GHashTable *listen_sockets)
 {
 	struct rspamd_worker *wrk;
-	gint rc;
-	struct rlimit rlim;
 
 	/* Starting worker process */
 	wrk = (struct rspamd_worker *) g_malloc0 (sizeof (struct rspamd_worker));
@@ -984,81 +1104,7 @@ rspamd_fork_worker (struct rspamd_main *rspamd_main,
 
 	switch (wrk->pid) {
 	case 0:
-		/* Update pid for logging */
-		rspamd_log_on_fork (cf->type, rspamd_main->cfg, rspamd_main->logger);
-		wrk->pid = getpid ();
-
-		/* Init PRNG after fork */
-		rc = ottery_init (rspamd_main->cfg->libs_ctx->ottery_cfg);
-		if (rc != OTTERY_ERR_NONE) {
-			msg_err_main ("cannot initialize PRNG: %d", rc);
-			abort ();
-		}
-
-		rspamd_random_seed_fast ();
-#ifdef HAVE_EVUTIL_RNG_INIT
-		evutil_secure_rng_init ();
-#endif
-
-		/*
-		 * Libev stores all signals in a global table, so
-		 * previous handlers must be explicitly detached and forgotten
-		 * before starting a new loop
-		 */
-		ev_signal_stop (rspamd_main->event_loop, &rspamd_main->int_ev);
-		ev_signal_stop (rspamd_main->event_loop, &rspamd_main->term_ev);
-		ev_signal_stop (rspamd_main->event_loop, &rspamd_main->hup_ev);
-		ev_signal_stop (rspamd_main->event_loop, &rspamd_main->usr1_ev);
-		/* Remove the inherited event base */
-		ev_loop_destroy (rspamd_main->event_loop);
-		rspamd_main->event_loop = NULL;
-		/* Drop privileges */
-		rspamd_worker_drop_priv (rspamd_main);
-		/* Set limits */
-		rspamd_worker_set_limits (rspamd_main, cf);
-		/* Re-set stack limit */
-		getrlimit (RLIMIT_STACK, &rlim);
-		rlim.rlim_cur = 100 * 1024 * 1024;
-		rlim.rlim_max = rlim.rlim_cur;
-		setrlimit (RLIMIT_STACK, &rlim);
-
-		if (cf->bind_conf) {
-			setproctitle ("%s process (%s)", cf->worker->name,
-					cf->bind_conf->bind_line);
-		}
-		else {
-			setproctitle ("%s process", cf->worker->name);
-		}
-
-		if (rspamd_main->pfh) {
-			rspamd_pidfile_close (rspamd_main->pfh);
-		}
-
-		if (rspamd_main->cfg->log_silent_workers) {
-			rspamd_log_set_log_level (rspamd_main->logger, G_LOG_LEVEL_MESSAGE);
-		}
-
-		wrk->start_time = rspamd_get_calendar_ticks ();
-
-		if (cf->bind_conf) {
-			msg_info_main ("starting %s process %P (%d); listen on: %s",
-					cf->worker->name,
-					getpid (), index, cf->bind_conf->bind_line);
-		}
-		else {
-			msg_info_main ("starting %s process %P (%d)", cf->worker->name,
-					getpid (), index);
-		}
-		/* Close parent part of socketpair */
-		close (wrk->control_pipe[0]);
-		close (wrk->srv_pipe[0]);
-		rspamd_socket_nonblocking (wrk->control_pipe[1]);
-		rspamd_socket_nonblocking (wrk->srv_pipe[1]);
-		rspamd_main->cfg->cur_worker = wrk;
-		/* Execute worker (this function should not return normally!) */
-		cf->worker->worker_start_func (wrk);
-		/* To distinguish from normal termination */
-		exit (EXIT_FAILURE);
+		rspamd_handle_child_fork (wrk, rspamd_main, cf, listen_sockets);
 		break;
 	case -1:
 		msg_err_main ("cannot fork main process: %s", strerror (errno));
diff --git a/src/libserver/worker_util.h b/src/libserver/worker_util.h
index 0e9e60545..c20108488 100644
--- a/src/libserver/worker_util.h
+++ b/src/libserver/worker_util.h
@@ -202,7 +202,8 @@ void rspamd_worker_session_cache_remove (void *cache, void *ptr);
 struct rspamd_worker *rspamd_fork_worker (struct rspamd_main *,
 										  struct rspamd_worker_conf *, guint idx,
 										  struct ev_loop *ev_base,
-										  rspamd_worker_term_cb term_handler);
+										  rspamd_worker_term_cb term_handler,
+										  GHashTable *listen_sockets);
 
 /**
  * Sets crash signals handlers if compiled with libunwind
diff --git a/src/rspamd.c b/src/rspamd.c
index dd47956a2..ff9ecfa88 100644
--- a/src/rspamd.c
+++ b/src/rspamd.c
@@ -373,7 +373,7 @@ rspamd_fork_delayed_cb (EV_P_ ev_timer *w, int revents)
 	rspamd_fork_worker (waiting_worker->rspamd_main, waiting_worker->cf,
 			waiting_worker->oldindex,
 			waiting_worker->rspamd_main->event_loop,
-			rspamd_cld_handler);
+			rspamd_cld_handler, listen_sockets);
 	REF_RELEASE (waiting_worker->cf);
 	g_free (waiting_worker);
 }
@@ -612,15 +612,17 @@ spawn_worker_type (struct rspamd_main *rspamd_main, struct ev_loop *event_loop,
 					"cannot spawn more than 1 %s worker, so spawn one",
 					cf->worker->name);
 		}
-		rspamd_fork_worker (rspamd_main, cf, 0, event_loop, rspamd_cld_handler);
+		rspamd_fork_worker (rspamd_main, cf, 0, event_loop, rspamd_cld_handler,
+				listen_sockets);
 	}
 	else if (cf->worker->flags & RSPAMD_WORKER_THREADED) {
-		rspamd_fork_worker (rspamd_main, cf, 0, event_loop, rspamd_cld_handler);
+		rspamd_fork_worker (rspamd_main, cf, 0, event_loop, rspamd_cld_handler,
+				listen_sockets);
 	}
 	else {
 		for (i = 0; i < cf->count; i++) {
 			rspamd_fork_worker (rspamd_main, cf, i, event_loop,
-					rspamd_cld_handler);
+					rspamd_cld_handler, listen_sockets);
 		}
 	}
 }


More information about the Commits mailing list