From: Jim Meyering Date: Wed, 21 Apr 2004 12:51:27 +0000 (+0000) Subject: - ls could incorrectly restore color if multiple signals X-Git-Tag: v5.3.0~1695 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=eae1b7f862ae45e7898304cd81332f12bd8fbdf7;p=thirdparty%2Fcoreutils.git - ls could incorrectly restore color if multiple signals arrived nearly simultaneously. (main): Rewrite signal-catching code to make it similar to other coreutils programs. When processing signals, block all signals that we catch, but do not block signals that we don't catch. Avoid problems with unsigned int warnings. (sighandler) [defined SA_NOCLDSTOP]: Use simpler "signal (sig, SIG_DFL)" rather than sigaction equivalent. (sighandler) [!defined SA_NOCLDSTOP]: Reset signal handler to self, not to SIG_IGN, since SIGTSTP can be received more than once. (main): Use SA_RESTART, as that is simpler than checking for EINTR failures all over the place. --- diff --git a/src/ls.c b/src/ls.c index 74d8cd4777..a96cdbaf89 100644 --- a/src/ls.c +++ b/src/ls.c @@ -973,33 +973,19 @@ restore_default_color (void) static void sighandler (int sig) { + /* SIGTSTP is special, since the application can receive that signal more + than once. In this case, don't set the signal handler to the default. + Instead, just raise the uncatchable SIGSTOP. */ #ifndef SA_NOCLDSTOP - signal (sig, SIG_IGN); + signal (sig, sig == SIGTSTP ? sighandler : SIG_IGN); #endif restore_default_color (); - /* SIGTSTP is special, since the application can receive that signal more - than once. In this case, don't set the signal handler to the default. - Instead, just raise the uncatchable SIGSTOP. */ if (sig == SIGTSTP) - { - sig = SIGSTOP; - } + sig = SIGSTOP; else - { -#ifdef SA_NOCLDSTOP - struct sigaction sigact; - - sigact.sa_handler = SIG_DFL; - sigemptyset (&sigact.sa_mask); - sigact.sa_flags = 0; - sigaction (sig, &sigact, NULL); -#else - signal (sig, SIG_DFL); -#endif - } - + signal (sig, SIG_DFL); raise (sig); } @@ -1043,34 +1029,35 @@ main (int argc, char **argv) check_symlink_color = 1; { - unsigned int j; - static int const sigs[] = { SIGHUP, SIGINT, SIGPIPE, - SIGQUIT, SIGTERM, SIGTSTP }; - unsigned int nsigs = sizeof sigs / sizeof *sigs; + int j; + static int const sig[] = { SIGHUP, SIGINT, SIGPIPE, + SIGQUIT, SIGTERM, SIGTSTP }; + enum { nsigs = sizeof sig / sizeof sig[0] }; + #ifdef SA_NOCLDSTOP - struct sigaction oldact, newact; + struct sigaction act; sigset_t caught_signals; sigemptyset (&caught_signals); for (j = 0; j < nsigs; j++) - sigaddset (&caught_signals, sigs[j]); - newact.sa_handler = sighandler; - newact.sa_mask = caught_signals; - newact.sa_flags = 0; -#endif + { + sigaction (sig[j], NULL, &act); + if (act.sa_handler != SIG_IGN) + sigaddset (&caught_signals, sig[j]); + } + + act.sa_handler = sighandler; + act.sa_mask = caught_signals; + act.sa_flags = SA_RESTART; for (j = 0; j < nsigs; j++) - { - int sig = sigs[j]; -#ifdef SA_NOCLDSTOP - sigaction (sig, NULL, &oldact); - if (oldact.sa_handler != SIG_IGN) - sigaction (sig, &newact, NULL); + if (sigismember (&caught_signals, sig[j])) + sigaction (sig[j], &act, NULL); #else - if (signal (sig, SIG_IGN) != SIG_IGN) - signal (sig, sighandler); + for (j = 0; j < nsigs; j++) + if (signal (sig[j], SIG_IGN) != SIG_IGN) + signal (sig[j], sighandler); #endif - } } }