Skip to content

Commit

Permalink
subthread signal handling
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
xTire committed Aug 30, 2024
1 parent d312ddc commit da21dc2
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 24 deletions.
23 changes: 11 additions & 12 deletions src/iperf_client_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
23 changes: 11 additions & 12 deletions src/iperf_server_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit da21dc2

Please sign in to comment.