diff --git a/src/iperf_api.c b/src/iperf_api.c index e35e102..68249c2 100644 --- a/src/iperf_api.c +++ b/src/iperf_api.c @@ -47,8 +47,6 @@ #include "iperf_util.h" #include "locale.h" -jmp_buf env; /* to handle longjmp on signal */ - /* Forwards. */ static int send_parameters(struct iperf_test *test); @@ -2109,12 +2107,27 @@ diskfile_recv(struct iperf_stream *sp) return r; } + void -sig_handler(int sig) +iperf_catch_sigend(void (*handler)(int)) { - longjmp(env, 1); + signal(SIGINT, handler); + signal(SIGTERM, handler); + signal(SIGHUP, handler); } +void +iperf_got_sigend(struct iperf_test *test) +{ + if (test->ctrl_sck >= 0) { + test->state = (test->role == 'c') ? CLIENT_TERMINATE : SERVER_TERMINATE; + (void) Nwrite(test->ctrl_sck, (char*) &test->state, sizeof(signed char), Ptcp); + } + i_errno = (test->role == 'c') ? IECLIENTTERM : IESERVERTERM; + iperf_errexit(test, "interrupt - %s", iperf_strerror(i_errno)); +} + + int iperf_json_start(struct iperf_test *test) { diff --git a/src/iperf_api.h b/src/iperf_api.h index 16c3433..4e03e57 100644 --- a/src/iperf_api.h +++ b/src/iperf_api.h @@ -169,7 +169,8 @@ int iperf_set_send_state(struct iperf_test *test, char state); void iperf_check_throttle(struct iperf_stream *sp, struct timeval *nowP); int iperf_send(struct iperf_test *, fd_set *) /* __attribute__((hot)) */; int iperf_recv(struct iperf_test *, fd_set *); -void sig_handler(int); +void iperf_catch_sigend(void (*handler)(int)); +void iperf_got_sigend(struct iperf_test *test) __attribute__ ((noreturn)); void usage(); void usage_long(); void warning(char *); diff --git a/src/iperf_client_api.c b/src/iperf_client_api.c index fe6a970..1f5718f 100644 --- a/src/iperf_client_api.c +++ b/src/iperf_client_api.c @@ -300,6 +300,15 @@ sigalrm_handler(int sig) } +static jmp_buf sigend_jmp_buf; + +static void +sigend_handler(int sig) +{ + longjmp(sigend_jmp_buf, 1); +} + + int iperf_run_client(struct iperf_test * test) { @@ -311,6 +320,11 @@ iperf_run_client(struct iperf_test * test) fd_set read_set, write_set; struct timeval now; + /* Termination signals. */ + iperf_catch_sigend(sigend_handler); + if (setjmp(sigend_jmp_buf)) + iperf_got_sigend(test); + if (test->affinity != -1) if (iperf_setaffinity(test->affinity) != 0) return -1; diff --git a/src/iperf_server_api.c b/src/iperf_server_api.c index 20bda6f..eab9438 100644 --- a/src/iperf_server_api.c +++ b/src/iperf_server_api.c @@ -330,6 +330,16 @@ cleanup_server(struct iperf_test *test) close(test->listener); } + +static jmp_buf sigend_jmp_buf; + +static void +sigend_handler(int sig) +{ + longjmp(sigend_jmp_buf, 1); +} + + int iperf_run_server(struct iperf_test *test) { @@ -338,6 +348,11 @@ iperf_run_server(struct iperf_test *test) struct iperf_stream *sp; struct timeval now; + /* Termination signals. */ + iperf_catch_sigend(sigend_handler); + if (setjmp(sigend_jmp_buf)) + iperf_got_sigend(test); + if (test->affinity != -1) if (iperf_setaffinity(test->affinity) != 0) return -1; diff --git a/src/main.c b/src/main.c index 09d0904..b5b14e4 100644 --- a/src/main.c +++ b/src/main.c @@ -30,10 +30,10 @@ #include "net.h" -int iperf_run(struct iperf_test *); +static int run(struct iperf_test *test); + /**************************************************************************/ - int main(int argc, char **argv) { @@ -81,19 +81,6 @@ main(int argc, char **argv) /* This main program doesn't use SIGALRM, so the iperf API may use it. */ iperf_set_test_may_use_sigalrm(test, 1); - // XXX: Check signal for errors? - signal(SIGINT, sig_handler); - if (setjmp(env)) { - if (test->ctrl_sck >= 0) { - test->state = (test->role == 'c') ? CLIENT_TERMINATE : SERVER_TERMINATE; - if (Nwrite(test->ctrl_sck, (char*) &test->state, sizeof(signed char), Ptcp) < 0) { - i_errno = IESENDMESSAGE; - return -1; - } - } - exit(1); - } - if (iperf_parse_arguments(test, argc, argv) < 0) { iperf_err(test, "parameter error - %s", iperf_strerror(i_errno)); fprintf(stderr, "\n"); @@ -101,7 +88,7 @@ main(int argc, char **argv) exit(1); } - if (iperf_run(test) < 0) + if (run(test) < 0) iperf_errexit(test, "error - %s", iperf_strerror(i_errno)); iperf_free_test(test); @@ -110,8 +97,8 @@ main(int argc, char **argv) } /**************************************************************************/ -int -iperf_run(struct iperf_test * test) +static int +run(struct iperf_test *test) { int consecutive_errors;