#define MAX_SIGNAL_VALUE 31
+#define SIGNAL_IS_TERMINAL(signo) \
+ ((signo) == SIGINT || (signo) == SIGQUIT || (signo) == SIGTERM)
+
#if !defined(SA_SIGINFO) && !defined(SI_NOINFO)
/* without SA_SIGINFO we don't know what the real code is. we need SI_NOINFO
to make sure lib_signal_code_to_str() returns "". */
struct signal_handler *next;
};
+volatile unsigned int signal_term_counter = 0;
+
/* Remember that these are accessed inside signal handler which may be called
even while we're initializing/deinitializing. Try hard to keep everything
in consistent state. */
if (signo < 0 || signo > MAX_SIGNAL_VALUE)
return;
+ if (SIGNAL_IS_TERMINAL(signo))
+ signal_term_counter++;
+
/* remember that we're inside a signal handler which might have been
called at any time. don't do anything that's unsafe. we might also
get interrupted by another signal while inside this handler. */
typedef void signal_handler_t(const siginfo_t *si, void *context);
+/* Number of times a "termination signal" has been received.
+ These signals are SIGINT, SIGQUIT and SIGTERM. Callers can compare this to
+ their saved previous value to see if a syscall returning EINTR should be
+ treated as someone wanting to end the process or just some internal signal
+ that should be ignored, such as SIGCHLD.
+
+ This is marked as volatile so that compiler won't optimize away its
+ comparisons. It may not work perfectly everywhere, such as when accessing it
+ isn't atomic, so you shouldn't heavily rely on its actual value. */
+extern volatile unsigned int signal_term_counter;
+
/* Convert si_code to string */
const char *lib_signal_code_to_str(int signo, int sicode);