Skip to content

Commit d5713db

Browse files
authored
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
1 parent 36deba4 commit d5713db

File tree

4 files changed

+40
-0
lines changed

4 files changed

+40
-0
lines changed

src/iperf_api.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,7 @@ enum {
475475
IEPTHREADJOIN=152, // Unable to join thread (check perror)
476476
IEPTHREADATTRINIT=153, // Unable to initialize thread attribute (check perror)
477477
IEPTHREADATTRDESTROY=154, // Unable to destroy thread attribute (check perror)
478+
IEPTHREADSIGMASK=155, // Unable to initialize sub thread signal mask (check perror)
478479
/* Stream errors */
479480
IECREATESTREAM = 200, // Unable to create a new stream (check herror/perror)
480481
IEINITSTREAM = 201, // Unable to initialize stream (check herror/perror)

src/iperf_client_api.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include <sys/select.h>
3737
#include <sys/uio.h>
3838
#include <arpa/inet.h>
39+
#include <signal.h>
3940

4041
#include "iperf.h"
4142
#include "iperf_api.h"
@@ -56,6 +57,23 @@ iperf_client_worker_run(void *s) {
5657
struct iperf_stream *sp = (struct iperf_stream *) s;
5758
struct iperf_test *test = sp->test;
5859

60+
/* Blocking signal to make sure that signal will be handled by main thread */
61+
sigset_t set;
62+
sigemptyset(&set);
63+
#ifdef SIGTERM
64+
sigaddset(&set, SIGTERM);
65+
#endif
66+
#ifdef SIGHUP
67+
sigaddset(&set, SIGHUP);
68+
#endif
69+
#ifdef SIGINT
70+
sigaddset(&set, SIGINT);
71+
#endif
72+
if (pthread_sigmask(SIG_BLOCK, &set, NULL) != 0) {
73+
i_errno = IEPTHREADSIGMASK;
74+
goto cleanup_and_fail;
75+
}
76+
5977
/* Allow this thread to be cancelled even if it's in a syscall */
6078
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
6179
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);

src/iperf_error.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,9 @@ iperf_strerror(int int_errno)
505505
snprintf(errstr, len, "unable to create thread attributes");
506506
perr = 1;
507507
break;
508+
case IEPTHREADSIGMASK:
509+
snprintf(errstr, len, "unable to change mask of blocked signals");
510+
break;
508511
case IEPTHREADATTRDESTROY:
509512
snprintf(errstr, len, "unable to destroy thread attributes");
510513
perr = 1;

src/iperf_server_api.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
#include <sys/resource.h>
4646
#include <sched.h>
4747
#include <setjmp.h>
48+
#include <signal.h>
4849

4950
#include "iperf.h"
5051
#include "iperf_api.h"
@@ -69,6 +70,23 @@ iperf_server_worker_run(void *s) {
6970
struct iperf_stream *sp = (struct iperf_stream *) s;
7071
struct iperf_test *test = sp->test;
7172

73+
/* Blocking signal to make sure that signal will be handled by main thread */
74+
sigset_t set;
75+
sigemptyset(&set);
76+
#ifdef SIGTERM
77+
sigaddset(&set, SIGTERM);
78+
#endif
79+
#ifdef SIGHUP
80+
sigaddset(&set, SIGHUP);
81+
#endif
82+
#ifdef SIGINT
83+
sigaddset(&set, SIGINT);
84+
#endif
85+
if (pthread_sigmask(SIG_BLOCK, &set, NULL) != 0) {
86+
i_errno = IEPTHREADSIGMASK;
87+
goto cleanup_and_fail;
88+
}
89+
7290
/* Allow this thread to be cancelled even if it's in a syscall */
7391
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
7492
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);

0 commit comments

Comments
 (0)