signal_handler_t *handler;
void *context;
- bool delayed;
+ enum libsig_flags flags;
struct signal_handler *next;
};
called at any time. don't do anything that's unsafe. we might also
get interrupted by another signal while inside this handler. */
for (h = signal_handlers[signo]; h != NULL; h = h->next) {
- if (!h->delayed)
+ if ((h->flags & LIBSIG_FLAG_DELAYED) == 0)
h->handler(si, h->context);
else if (pending_signals[signo].si_signo == 0) {
pending_signals[signo] = *si;
continue;
for (h = signal_handlers[signo]; h != NULL; h = h->next) {
- if (h->delayed)
+ if ((h->flags & LIBSIG_FLAG_DELAYED) != 0)
h->handler(&signals[signo], h->context);
}
}
}
-static void lib_signals_set(int signo)
+static void lib_signals_set(int signo, enum libsig_flags flags)
{
struct sigaction act;
act.sa_flags = 0;
act.sa_handler = sig_handler;
#endif
+ if ((flags & LIBSIG_FLAG_RESTART) != 0)
+ act.sa_flags |= SA_RESTART;
if (sigaction(signo, &act, NULL) < 0)
i_fatal("sigaction(%d): %m", signo);
}
-void lib_signals_set_handler(int signo, bool delayed,
+void lib_signals_set_handler(int signo, enum libsig_flags flags,
signal_handler_t *handler, void *context)
{
struct signal_handler *h;
}
if (signal_handlers[signo] == NULL && signals_initialized)
- lib_signals_set(signo);
+ lib_signals_set(signo, flags);
- if (delayed && sig_pipe_fd[0] == -1) {
+ if ((flags & LIBSIG_FLAG_DELAYED) != 0 && sig_pipe_fd[0] == -1) {
/* first delayed handler */
if (pipe(sig_pipe_fd) < 0)
i_fatal("pipe() failed: %m");
h = i_new(struct signal_handler, 1);
h->handler = handler;
h->context = context;
- h->delayed = delayed;
+ h->flags = flags;
/* atomically set to signal_handlers[] list */
h->next = signal_handlers[signo];
/* add signals that were already registered */
for (i = 0; i < MAX_SIGNAL_VALUE; i++) {
if (signal_handlers[i] != NULL)
- lib_signals_set(i);
+ lib_signals_set(i, signal_handlers[i]->flags);
}
if (sig_pipe_fd[0] != -1)
#include <signal.h>
+enum libsig_flags {
+ /* Signal handler will be called later from IO loop when it's safe to
+ do any kind of work */
+ LIBSIG_FLAG_DELAYED = 0x01,
+ /* Restart syscalls instead of having them fail with EINTR */
+ LIBSIG_FLAG_RESTART = 0x02
+};
+#define LIBSIG_FLAGS_SAFE (LIBSIG_FLAG_DELAYED | LIBSIG_FLAG_RESTART)
+
typedef void signal_handler_t(const siginfo_t *si, void *context);
/* Number of times a "termination signal" has been received.
/* Convert si_code to string */
const char *lib_signal_code_to_str(int signo, int sicode);
-/* Set signal handler for specific signal. If delayed is TRUE, the handler
- will be called later, ie. not as a real signal handler. */
-void lib_signals_set_handler(int signo, bool delayed,
+/* Set signal handler for specific signal. */
+void lib_signals_set_handler(int signo, enum libsig_flags flags,
signal_handler_t *handler, void *context);
/* Ignore given signal. */
void lib_signals_ignore(int signo, bool restart_syscalls);