From da21dc205821d96187026563237a374e0fe7c260 Mon Sep 17 00:00:00 2001 From: Sheng Jie Date: Fri, 30 Aug 2024 23:23:55 +0800 Subject: [PATCH] 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. --- src/iperf_client_api.c | 23 +++++++++++------------ src/iperf_server_api.c | 23 +++++++++++------------ 2 files changed, 22 insertions(+), 24 deletions(-) diff --git a/src/iperf_client_api.c b/src/iperf_client_api.c index aa3559f48..eb39c27c9 100644 --- a/src/iperf_client_api.c +++ b/src/iperf_client_api.c @@ -57,6 +57,17 @@ 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); + sigaddset(&set, SIGTERM); + sigaddset(&set, SIGHUP); + sigaddset(&set, SIGINT); + 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); @@ -688,18 +699,6 @@ iperf_run_client(struct iperf_test * test) goto cleanup_and_fail; } - /* Block signals that handled by main thread, sub thread(s) will - * inherit a copy of the signal mask */ - sigset_t set; - sigemptyset(&set); - sigaddset(&set, SIGTERM); - sigaddset(&set, SIGHUP); - sigaddset(&set, SIGINT); - if (pthread_sigmask(SIG_BLOCK, &set, NULL) != 0) { - i_errno = IEPTHREADSIGMASK; - goto cleanup_and_fail; - } - SLIST_FOREACH(sp, &test->streams, streams) { if (pthread_create(&(sp->thr), &attr, &iperf_client_worker_run, sp) != 0) { i_errno = IEPTHREADCREATE; diff --git a/src/iperf_server_api.c b/src/iperf_server_api.c index d6aa6bdd3..c2270cc56 100644 --- a/src/iperf_server_api.c +++ b/src/iperf_server_api.c @@ -70,6 +70,17 @@ 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); + sigaddset(&set, SIGTERM); + sigaddset(&set, SIGHUP); + sigaddset(&set, SIGINT); + 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); @@ -886,18 +897,6 @@ iperf_run_server(struct iperf_test *test) cleanup_server(test); }; - /* Block signals that handled by main thread, sub thread(s) will - * inherit a copy of the signal mask */ - sigset_t set; - sigemptyset(&set); - sigaddset(&set, SIGTERM); - sigaddset(&set, SIGHUP); - sigaddset(&set, SIGINT); - if (pthread_sigmask(SIG_BLOCK, &set, NULL) != 0) { - i_errno = IEPTHREADSIGMASK; - cleanup_server(test); - } - SLIST_FOREACH(sp, &test->streams, streams) { if (pthread_create(&(sp->thr), &attr, &iperf_server_worker_run, sp) != 0) { i_errno = IEPTHREADCREATE;