From c557191ca02f326bd314963f88118301d891aa89 Mon Sep 17 00:00:00 2001
From: Libor Peltan <libor.peltan@nic.cz>
Date: Fri, 30 Aug 2024 10:29:49 +0200
Subject: [PATCH] concurrent CTL: disable signals temporarily when launching
 subthreads to avoid losing them

---
 src/utils/knotd/main.c | 24 ++++++++++++++++++++++--
 1 file changed, 22 insertions(+), 2 deletions(-)

diff --git a/src/utils/knotd/main.c b/src/utils/knotd/main.c
index 203d31324d..d141f74fce 100644
--- a/src/utils/knotd/main.c
+++ b/src/utils/knotd/main.c
@@ -66,6 +66,7 @@ typedef struct {
 	knot_ctl_t *ctl;
 	server_t *server;
 	pthread_t thread;
+	sigset_t sigmask;
 	int ret;
 	bool exclusive;
 } concurrent_ctl_ctx_t;
@@ -184,13 +185,14 @@ static void setup_signals(void)
 	sigdelset(&all, SIGBUS);
 	sigdelset(&all, SIGFPE);
 	sigdelset(&all, SIGSEGV);
-	pthread_sigmask(SIG_SETMASK, &all, NULL);
 
 	/* Setup handlers. */
 	struct sigaction action = { .sa_handler = handle_signal };
 	for (const struct signal *s = SIGNALS; s->signum > 0; s++) {
 		sigaction(s->signum, &action, NULL);
 	}
+
+	pthread_sigmask(SIG_SETMASK, &all, NULL);
 }
 
 /*! \brief Unblock server control signals. */
@@ -208,6 +210,24 @@ static void enable_signals(void)
 	pthread_sigmask(SIG_UNBLOCK, &mask, NULL);
 }
 
+/*! \brief Create a control thread with correct signals setting. */
+static void create_thread_sigmask(pthread_t *thr, void *(*fcn)(void*), void *ctx,
+                                  sigset_t *out_mask)
+{
+	/* Block all blockable signals. */
+	sigset_t mask;
+	sigfillset(&mask);
+	sigdelset(&mask, SIGBUS);
+	sigdelset(&mask, SIGFPE);
+	sigdelset(&mask, SIGILL);
+	sigdelset(&mask, SIGSEGV);
+	pthread_sigmask(SIG_SETMASK, &mask, out_mask);
+
+	pthread_create(thr, NULL, fcn, ctx);
+
+	pthread_sigmask(SIG_SETMASK, out_mask, NULL);
+}
+
 /*! \brief Drop POSIX 1003.1e capabilities. */
 static void drop_capabilities(void)
 {
@@ -306,7 +326,7 @@ static concurrent_ctl_ctx_t *find_free_ctx(concurrent_ctl_ctx_t *concurrent_ctxs
 		pthread_mutex_lock(&cctx->mutex);
 		switch (cctx->state) {
 		case CONCURRENT_EMPTY:
-			pthread_create(&cctx->thread, NULL, ctl_process_thread, cctx);
+			create_thread_sigmask(&cctx->thread, ctl_process_thread, cctx, &cctx->sigmask);
 			break;
 		case CONCURRENT_IDLE:
 			knot_ctl_free(cctx->ctl);
-- 
GitLab