diff --git a/core/src/daemon.c b/core/src/daemon.c index e3463fc..eae23ec 100644 --- a/core/src/daemon.c +++ b/core/src/daemon.c @@ -306,6 +306,35 @@ void handler_alarm(int unused) return; } +int process_switch_sig(int sig) +{ + /* Switch from silent to verbose. */ + if (sig == SIGUSR1) { + pthread_mutex_lock(&mtx_paint); + pthread_mutex_lock(&mtx_tty); + ioctl(fd_tty[config.tty_s], VT_RELDISP, 1); + pthread_mutex_unlock(&mtx_tty); + + ctty = CTTY_VERBOSE; + pthread_mutex_unlock(&mtx_paint); + return 1; + /* Switch back to silent. */ + } else if (sig == SIGUSR2) { + pthread_mutex_lock(&mtx_paint); + pthread_mutex_lock(&mtx_tty); + ioctl(fd_tty[config.tty_s], VT_RELDISP, 2); + pthread_mutex_unlock(&mtx_tty); + + ctty = CTTY_SILENT; + pthread_mutex_unlock(&mtx_paint); + + switch_silent(); + return 2; + } + + return 0; +} + /* * Signal handler. * @@ -315,7 +344,7 @@ void handler_alarm(int unused) */ void* thf_sighandler(void *unusued) { - sigset_t sigset; + sigset_t sigset, sigset_switch; int sig; /* We don't handle SIGALRM. */ @@ -329,31 +358,39 @@ void* thf_sighandler(void *unusued) sigaddset(&sigset, SIGTERM); sigaddset(&sigset, SIGINT); + sigemptyset(&sigset_switch); + sigaddset(&sigset_switch, SIGUSR1); + sigaddset(&sigset_switch, SIGUSR2); + while (1) { sigwait(&sigset, &sig); - /* Switch from silent to verbose. */ - if (sig == SIGUSR1) { - pthread_mutex_lock(&mtx_paint); - pthread_mutex_lock(&mtx_tty); - ioctl(fd_tty[config.tty_s], VT_RELDISP, 1); - pthread_mutex_unlock(&mtx_tty); - - ctty = CTTY_VERBOSE; - pthread_mutex_unlock(&mtx_paint); - /* Switch back to silent. */ - } else if (sig == SIGUSR2) { - pthread_mutex_lock(&mtx_paint); - pthread_mutex_lock(&mtx_tty); - ioctl(fd_tty[config.tty_s], VT_RELDISP, 2); - pthread_mutex_unlock(&mtx_tty); - - ctty = CTTY_SILENT; - pthread_mutex_unlock(&mtx_paint); + process_switch_sig(sig); + + /* Internally generated terminate signal */ + if (sig == SIGINT) { + struct timespec timeout; + timeout.tv_sec = 0; + timeout.tv_nsec = 0; + bool pending = true; + + /* + * Process any remaining signals. There are no guarantees as to the + * order in which the signals are delivered, so we have to make sure + * all pending signals are processed before exiting. + */ + while (pending) { + sig = sigtimedwait(&sigset_switch, NULL, &timeout); + + if (sig == -1) { + /* No more pending signals. */ + if (errno == EAGAIN) + pending = false; + } else { + process_switch_sig(sig); + } + } - switch_silent(); - } else if (sig == SIGINT) { - /* internally generated terminate signal */ do_cleanup(); pthread_exit(NULL); } else if (sig == SIGTERM) {