diff --git a/src/iperf_api.c b/src/iperf_api.c index 6fbd79f84..10d360c75 100644 --- a/src/iperf_api.c +++ b/src/iperf_api.c @@ -4874,8 +4874,10 @@ iperf_catch_sigend(void (*handler)(int)) * before cleaning up and exiting. */ void -iperf_got_sigend(struct iperf_test *test) +iperf_got_sigend(struct iperf_test *test, int sig) { + int exit_normal; + /* * If we're the client, or if we're a server and running a test, * then dump out the accumulated stats so far. @@ -4897,7 +4899,25 @@ iperf_got_sigend(struct iperf_test *test) (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)); + + exit_normal = 0; +#ifdef SIGTERM + if (sig == SIGTERM) + exit_normal = 1; +#endif +#ifdef SIGINT + if (sig == SIGINT) + exit_normal = 1; +#endif +#ifdef SIGHUP + if (sig == SIGHUP) + exit_normal = 1; +#endif + if (exit_normal) { + iperf_signormalexit(test, "interrupt - %s by signal %s(%d)", iperf_strerror(i_errno), strsignal(sig), sig); + } else { + iperf_errexit(test, "interrupt - %s by signal %s(%d)", iperf_strerror(i_errno), strsignal(sig), sig); + } } /* Try to write a PID file if requested, return -1 on an error. */ diff --git a/src/iperf_api.h b/src/iperf_api.h index 471cc9032..55e1aa626 100644 --- a/src/iperf_api.h +++ b/src/iperf_api.h @@ -327,7 +327,7 @@ void iperf_check_throttle(struct iperf_stream *sp, struct iperf_time *nowP); int iperf_send_mt(struct iperf_stream *) /* __attribute__((hot)) */; int iperf_recv_mt(struct iperf_stream *); void iperf_catch_sigend(void (*handler)(int)); -void iperf_got_sigend(struct iperf_test *test) __attribute__ ((noreturn)); +void iperf_got_sigend(struct iperf_test *test, int sig) __attribute__ ((noreturn)); void usage(void); void usage_long(FILE * f); void warning(const char *); @@ -381,6 +381,8 @@ int iflush(struct iperf_test *test); /* Error routines. */ void iperf_err(struct iperf_test *test, const char *format, ...) __attribute__ ((format(printf,2,3))); void iperf_errexit(struct iperf_test *test, const char *format, ...) __attribute__ ((format(printf,2,3),noreturn)); +void iperf_signormalexit(struct iperf_test *test, const char *format, ...) __attribute__ ((format(printf,2,3),noreturn)); +void iperf_exit(struct iperf_test *test, int exit_code, const char *format, va_list argp) __attribute__ ((noreturn)); char *iperf_strerror(int); extern int i_errno; enum { diff --git a/src/iperf_error.c b/src/iperf_error.c index d0da8e8af..34bbb1290 100644 --- a/src/iperf_error.c +++ b/src/iperf_error.c @@ -85,11 +85,30 @@ iperf_err(struct iperf_test *test, const char *format, ...) va_end(argp); } -/* Do a printf to stderr or log file as appropriate, then exit. */ +/* Do a printf to stderr or log file as appropriate, then exit(0). */ +void +iperf_signormalexit(struct iperf_test *test, const char *format, ...) +{ + va_list argp; + + va_start(argp, format); + iperf_exit(test, 0, format, argp); +} + +/* Do a printf to stderr or log file as appropriate, then exit(1). */ void iperf_errexit(struct iperf_test *test, const char *format, ...) { va_list argp; + + va_start(argp, format); + iperf_exit(test, 1, format, argp); +} + +/* Do a printf to stderr or log file as appropriate, then exit. */ +void +iperf_exit(struct iperf_test *test, int exit_code, const char *format, va_list argp) +{ char str[1000]; time_t now; struct tm *ltm = NULL; @@ -103,7 +122,6 @@ iperf_errexit(struct iperf_test *test, const char *format, ...) ct = iperf_timestrerr; } - va_start(argp, format); vsnprintf(str, sizeof(str), format, argp); if (test != NULL && test->json_output) { if (test->json_top != NULL) { @@ -136,7 +154,7 @@ iperf_errexit(struct iperf_test *test, const char *format, ...) va_end(argp); if (test) iperf_delete_pidfile(test); - exit(1); + exit(exit_code); } int i_errno; diff --git a/src/main.c b/src/main.c index eb29f87ac..708fd4f4c 100644 --- a/src/main.c +++ b/src/main.c @@ -131,10 +131,12 @@ main(int argc, char **argv) static jmp_buf sigend_jmp_buf; +static int signed_sig; static void __attribute__ ((noreturn)) sigend_handler(int sig) { + signed_sig = sig; longjmp(sigend_jmp_buf, 1); } @@ -145,7 +147,7 @@ run(struct iperf_test *test) /* Termination signals. */ iperf_catch_sigend(sigend_handler); if (setjmp(sigend_jmp_buf)) - iperf_got_sigend(test); + iperf_got_sigend(test, signed_sig); /* Ignore SIGPIPE to simplify error handling */ signal(SIGPIPE, SIG_IGN);