]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
Bug 2971 - ntpq bails on ^C: select fails: Interrupted system call
authorJuergen Perlinger <perlinger@ntp.org>
Sat, 28 Nov 2015 18:09:53 +0000 (19:09 +0100)
committerJuergen Perlinger <perlinger@ntp.org>
Sat, 28 Nov 2015 18:09:53 +0000 (19:09 +0100)
 - changed stacked/nested handling of CTRL-C.

bk: 5659edf14gdulYozwy2PmJ1TsnHQ_A

ChangeLog
ntpq/ntpq-subs.c
ntpq/ntpq.c
ntpq/ntpq.h

index a787d4306b28c0d33452f9df3df4f4183874717b..bd0e8233ed4c451a93ca75ada00ec083e1648093 100644 (file)
--- 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.
index b81dc379c1785daa81ae42e09e4fe53a7c034a00..438c7ca58a65054702a0e0ddf60797f330d30d47 100644 (file)
@@ -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);
 }
 
 
index fe3fbac8b2a5ad5c69b3b2509ecbb8204a35e8b5..5b3c9cb807b7fa144af95479ef2eabc9ae031d5e 100644 (file)
@@ -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;
+}
index 171b807689ff7ee37ad15cbf4516becd8e9e5927..55ea0fb5c3622a1464efc2c6139f913889309114 100644 (file)
@@ -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);