From: Juergen Perlinger Date: Sat, 28 Nov 2015 18:09:53 +0000 (+0100) Subject: Bug 2971 - ntpq bails on ^C: select fails: Interrupted system call X-Git-Tag: NTP_4_3_85~2^2^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0fd9376b197e1dd97b455804d37e5b345d096dab;p=thirdparty%2Fntp.git Bug 2971 - ntpq bails on ^C: select fails: Interrupted system call - changed stacked/nested handling of CTRL-C. bk: 5659edf14gdulYozwy2PmJ1TsnHQ_A --- diff --git a/ChangeLog b/ChangeLog index a787d4306..bd0e8233e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -22,6 +22,8 @@ * [Bug 2965] Local clock didn't work since 4.2.8p4. Martin Burnicki. * [Bug 2969] Seg fault from ntpq/mrulist when looking at server with lots of clients. perlinger@ntp.org +* [Bug 2971] ntpq bails on ^C: select fails: Interrupted system call + - changed stacked/nested handling of CTRL-C. perlinger@ntp.org * Unity cleanup for FreeBSD-6.4. Harlan Stenn. * Unity test cleanup. Harlan Stenn. * Libevent autoconf pthread fixes for FreeBSD-10. Harlan Stenn. diff --git a/ntpq/ntpq-subs.c b/ntpq/ntpq-subs.c index b81dc379c..438c7ca58 100644 --- a/ntpq/ntpq-subs.c +++ b/ntpq/ntpq-subs.c @@ -343,7 +343,7 @@ typedef struct var_display_collection_tag { /* * other local function prototypes */ -void mrulist_ctrl_c_hook(void); +static int mrulist_ctrl_c_hook(void); static mru * add_mru(mru *); static int collect_mru_list(const char *, l_fp *); static int fetch_nonce(char *, size_t); @@ -2422,10 +2422,11 @@ add_mru( } while (0) -void +int mrulist_ctrl_c_hook(void) { mrulist_interrupted = TRUE; + return TRUE; } @@ -2496,11 +2497,6 @@ collect_mru_list( mon = emalloc_zero(cb); ZERO(*pnow); ZERO(last_older); - mrulist_interrupted = FALSE; - set_ctrl_c_hook(&mrulist_ctrl_c_hook); - fprintf(stderr, - "Ctrl-C will stop MRU retrieval and display partial results.\n"); - fflush(stderr); next_report = time(NULL) + MRU_REPORT_SECS; limit = min(3 * MAXFRAGS, ntpd_row_limit); @@ -2872,7 +2868,6 @@ collect_mru_list( } } - set_ctrl_c_hook(NULL); c_mru_l_rc = TRUE; goto retain_hash_table; @@ -3082,6 +3077,12 @@ mrulist( int lstint; size_t i; + mrulist_interrupted = FALSE; + push_ctrl_c_handler(&mrulist_ctrl_c_hook); + fprintf(stderr, + "Ctrl-C will stop MRU retrieval and display partial results.\n"); + fflush(stderr); + order = MRUSORT_DEF; parms_buf[0] = '\0'; parms = parms_buf; @@ -3222,6 +3223,8 @@ cleanup_return: free(hash_table); hash_table = NULL; INIT_DLIST(mru_list, mlink); + + pop_ctrl_c_handler(&mrulist_ctrl_c_hook); } diff --git a/ntpq/ntpq.c b/ntpq/ntpq.c index fe3fbac8b..5b3c9cb80 100644 --- a/ntpq/ntpq.c +++ b/ntpq/ntpq.c @@ -175,7 +175,7 @@ static char * tstflags (u_long); #ifndef BUILD_AS_LIB static void getcmds (void); #ifndef SYS_WINNT -static RETSIGTYPE abortcmd (int); +static int abortcmd (void); #endif /* SYS_WINNT */ static void docmd (const char *); static void tokenize (const char *, char **, int *); @@ -216,6 +216,7 @@ static void output (FILE *, const char *, const char *); static void endoutput (FILE *); static void outputarr (FILE *, char *, int, l_fp *); static int assoccmp (const void *, const void *); +static void on_ctrlc (void); u_short varfmt (const char *); void ntpq_custom_opt_handler (tOptions *, tOptDesc *); @@ -559,9 +560,10 @@ ntpqmain( interactive = 1; } + set_ctrl_c_hook(on_ctrlc); #ifndef SYS_WINNT /* Under NT cannot handle SIGINT, WIN32 spawns a handler */ if (interactive) - (void) signal_no_reset(SIGINT, abortcmd); + push_ctrl_c_handler(abortcmd); #endif /* SYS_WINNT */ if (numcmds == 0) { @@ -1460,16 +1462,18 @@ getcmds(void) /* * abortcmd - catch interrupts and abort the current command */ -static RETSIGTYPE -abortcmd( - int sig - ) +static int +abortcmd(void) { if (current_output == stdout) - (void) fflush(stdout); + (void) fflush(stdout); putc('\n', stderr); (void) fflush(stderr); - if (jump) longjmp(interrupt_buf, 1); + if (jump) { + jump = 0; + longjmp(interrupt_buf, 1); + } + return TRUE; } #endif /* !SYS_WINNT && !BUILD_AS_LIB */ @@ -3566,3 +3570,48 @@ static char *list_digest_names(void) return list; } + +#define CTRLC_STACK_MAX 4 +static volatile size_t ctrlc_stack_len = 0; +static volatile Ctrl_C_Handler ctrlc_stack[CTRLC_STACK_MAX]; + + + +int/*BOOL*/ +push_ctrl_c_handler( + Ctrl_C_Handler func + ) +{ + size_t size = ctrlc_stack_len; + if (func && (size < CTRLC_STACK_MAX)) { + ctrlc_stack[size] = func; + ctrlc_stack_len = size + 1; + return TRUE; + } + return FALSE; +} + +int/*BOOL*/ +pop_ctrl_c_handler( + Ctrl_C_Handler func + ) +{ + size_t size = ctrlc_stack_len; + if (size) { + --size; + if (func == NULL || func == ctrlc_stack[size]) { + ctrlc_stack_len = size; + return TRUE; + } + } + return FALSE; +} + +static void +on_ctrlc(void) +{ + size_t size = ctrlc_stack_len; + while (size) + if ((*ctrlc_stack[--size])()) + break; +} diff --git a/ntpq/ntpq.h b/ntpq/ntpq.h index 171b80768..55ea0fb5c 100644 --- a/ntpq/ntpq.h +++ b/ntpq/ntpq.h @@ -152,3 +152,7 @@ extern int decodeint (char *, long *); extern void makeascii (size_t, const char *, FILE *); extern const char * trunc_left (const char *, size_t); extern const char * trunc_right(const char *, size_t); + +typedef int/*BOOL*/ (*Ctrl_C_Handler)(void); +extern int/*BOOL*/ push_ctrl_c_handler(Ctrl_C_Handler); +extern int/*BOOL*/ pop_ctrl_c_handler(Ctrl_C_Handler);