From d5713db9dec9abb98b37f4b9904991ebdc5da59b Mon Sep 17 00:00:00 2001 From: Jie Sheng Date: Fri, 13 Sep 2024 11:05:12 +0800 Subject: [PATCH] Avoid subthread signal handling (#1752) * Avoid subthread signal handling * subthread signal handling Since multiple threads responding simultaneously to a signal leading to race condition, this is used to ensure that only the main thread handles the signal. * aesthetic improvements * Revert IEPTHREADATTRDESTROY to original value --- src/iperf_api.h | 1 + src/iperf_client_api.c | 18 ++++++++++++++++++ src/iperf_error.c | 3 +++ src/iperf_server_api.c | 18 ++++++++++++++++++ 4 files changed, 40 insertions(+) diff --git a/src/iperf_api.h b/src/iperf_api.h index 131314243..2b71613e9 100644 --- a/src/iperf_api.h +++ b/src/iperf_api.h @@ -475,6 +475,7 @@ enum { IEPTHREADJOIN=152, // Unable to join thread (check perror) IEPTHREADATTRINIT=153, // Unable to initialize thread attribute (check perror) IEPTHREADATTRDESTROY=154, // Unable to destroy thread attribute (check perror) + IEPTHREADSIGMASK=155, // Unable to initialize sub thread signal mask (check perror) /* Stream errors */ IECREATESTREAM = 200, // Unable to create a new stream (check herror/perror) IEINITSTREAM = 201, // Unable to initialize stream (check herror/perror) diff --git a/src/iperf_client_api.c b/src/iperf_client_api.c index 7c22caded..c26bcc27a 100644 --- a/src/iperf_client_api.c +++ b/src/iperf_client_api.c @@ -36,6 +36,7 @@ #include #include #include +#include #include "iperf.h" #include "iperf_api.h" @@ -56,6 +57,23 @@ iperf_client_worker_run(void *s) { struct iperf_stream *sp = (struct iperf_stream *) s; struct iperf_test *test = sp->test; + /* Blocking signal to make sure that signal will be handled by main thread */ + sigset_t set; + sigemptyset(&set); +#ifdef SIGTERM + sigaddset(&set, SIGTERM); +#endif +#ifdef SIGHUP + sigaddset(&set, SIGHUP); +#endif +#ifdef SIGINT + sigaddset(&set, SIGINT); +#endif + if (pthread_sigmask(SIG_BLOCK, &set, NULL) != 0) { + i_errno = IEPTHREADSIGMASK; + goto cleanup_and_fail; + } + /* Allow this thread to be cancelled even if it's in a syscall */ pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); diff --git a/src/iperf_error.c b/src/iperf_error.c index ce925a81f..3388d376e 100644 --- a/src/iperf_error.c +++ b/src/iperf_error.c @@ -505,6 +505,9 @@ iperf_strerror(int int_errno) snprintf(errstr, len, "unable to create thread attributes"); perr = 1; break; + case IEPTHREADSIGMASK: + snprintf(errstr, len, "unable to change mask of blocked signals"); + break; case IEPTHREADATTRDESTROY: snprintf(errstr, len, "unable to destroy thread attributes"); perr = 1; diff --git a/src/iperf_server_api.c b/src/iperf_server_api.c index b87734fec..9727cdddb 100644 --- a/src/iperf_server_api.c +++ b/src/iperf_server_api.c @@ -45,6 +45,7 @@ #include #include #include +#include #include "iperf.h" #include "iperf_api.h" @@ -69,6 +70,23 @@ iperf_server_worker_run(void *s) { struct iperf_stream *sp = (struct iperf_stream *) s; struct iperf_test *test = sp->test; + /* Blocking signal to make sure that signal will be handled by main thread */ + sigset_t set; + sigemptyset(&set); +#ifdef SIGTERM + sigaddset(&set, SIGTERM); +#endif +#ifdef SIGHUP + sigaddset(&set, SIGHUP); +#endif +#ifdef SIGINT + sigaddset(&set, SIGINT); +#endif + if (pthread_sigmask(SIG_BLOCK, &set, NULL) != 0) { + i_errno = IEPTHREADSIGMASK; + goto cleanup_and_fail; + } + /* Allow this thread to be cancelled even if it's in a syscall */ pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);