lib-signals.c revision b0aa6aa9a8a485b18fa24579fb0da38f08a3b196
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2001-2003 Timo Sirainen */
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen/* Remember that these are accessed inside signal handler which may be called
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen even while we're initializing/deinitializing. Try hard to keep everything
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen in consistent state. */
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenstatic struct signal_handler *signal_handlers[MAX_SIGNAL_VALUE+1];
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen /* remember that we're inside a signal handler which might have been
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen called at any time. don't do anything that's unsafe. */
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen for (h = signal_handlers[signo]; h != NULL; h = h->next) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (write(sig_pipe_fd[1], &signo_byte, 1) != 1)
2200adee458ca662d32b5ec0e01d8c5cba0cc0a8Timo Sirainenstatic void sig_ignore(int signo __attr_unused__)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen /* if we used SIG_IGN instead of this function,
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen the system call might be restarted */
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenstatic void signal_read(void *context __attr_unused__)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen unsigned char signal_mask[MAX_SIGNAL_VALUE+1];
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen ret = read(sig_pipe_fd[0], signal_buf, sizeof(signal_buf));
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen /* move them to mask first to avoid calling same handler
35ef661bd85c64834e3e34eeeb3c393b81108760Timo Sirainen multiple times */
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen for (i = 0; i < ret; i++) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen /* call the delayed handlers */
c39c3d8089fbdd8eb34646c25167aa4551064cf4Timo Sirainen for (signo = 0; signo < MAX_SIGNAL_VALUE; signo++) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen } else if (ret < 0) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenvoid lib_signals_set_handler(int signo, bool delayed,
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen i_panic("Trying to set signal %d handler, but max is %d",
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen /* first handler for this signal */
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen act.sa_handler = handler != NULL ? sig_handler : sig_ignore;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen /* we're ignoring the handler, just return */
5fa253bd316540ec280ca76b39d62a9e32da228bTimo Sirainen /* first delayed handler */
5fa253bd316540ec280ca76b39d62a9e32da228bTimo Sirainen io_sig = io_add(sig_pipe_fd[0], IO_READ, signal_read, NULL);
e18e90938ffd9e31c796c405404be0b7dcd5c807Timo Sirainen /* atomically set to signal_handlers[] list */
e18e90938ffd9e31c796c405404be0b7dcd5c807Timo Sirainen i_panic("Trying to ignore signal %d, but max is %d",
e18e90938ffd9e31c796c405404be0b7dcd5c807Timo Sirainenvoid lib_signals_unset_handler(int signo, signal_handler_t *handler,
e18e90938ffd9e31c796c405404be0b7dcd5c807Timo Sirainen struct signal_handler *h, **p;
e18e90938ffd9e31c796c405404be0b7dcd5c807Timo Sirainen for (p = &signal_handlers[signo]; *p != NULL; p = &(*p)->next) {
e18e90938ffd9e31c796c405404be0b7dcd5c807Timo Sirainen if ((*p)->handler == handler && (*p)->context == context) {
e18e90938ffd9e31c796c405404be0b7dcd5c807Timo Sirainen i_panic("lib_signals_unset_handler(%d, %p, %p): handler not found",
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen memset(signal_handlers, 0, sizeof(signal_handlers));
2f19f8ff906a0017b906763e0f7675d49ab0e58fTimo Sirainen for (i = 0; i < MAX_SIGNAL_VALUE; i++) {
2f19f8ff906a0017b906763e0f7675d49ab0e58fTimo Sirainen /* atomically remove from signal_handlers[] list */