/*- * redshift-ng - Automatically adjust display colour temperature according the Sun * * Copyright (c) 2009-2018 Jon Lund Steffensen * Copyright (c) 2014-2016, 2025 Mattias Andrée * * redshift-ng is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * redshift-ng is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with redshift-ng. If not, see . */ #include "common.h" volatile sig_atomic_t exiting = 0; volatile sig_atomic_t disable = 0; volatile enum signals signals = 0; /** * Signal handler for exit signals (SIGINT, SIGTERM, SIGQUIT) * * @param signo The received signal */ static void sigexit(int signo) { exiting = 1; #ifdef WINDOWS signal(signo, &sigexit); #endif (void) signo; } #ifndef WINDOWS /** * Signal handler for disable signal (SIGUSR1) * * @param signo The received signal */ static void sigdisable(int signo) { disable = 1; (void) signo; } /** * Signal handler for forceful exiting; installed by * `install_forceful_exit_signal_handlers` * * @param signo The received signal */ static void sigalrm(int signo) { if (exiting || signo == SIGALRM) exit(0); exiting = 1; alarm(1U); } /** * Signal handler for SIGUSR2 * * @param signo The received signal * @param info The received signal data * @param uctx Interrupted stack context */ static void sigipc(int signo, siginfo_t *info, void *uctx) { int set, mask; sigset_t sigusr2_mask; (void) signo; (void) uctx; if (info->si_code != SI_QUEUE) return; switch (info->si_value.sival_int) { case 1: case 2: mask = 3 << 1; break; case 5: case 6: mask = 3 << 5; break; case 7: case 8: mask = 3 << 7; break; case 11: case 12: mask = 3 << 11; break; case 0: case 3: case 4: case 9: case 10: mask = 0; break; default: return; } signals |= set = 1 << info->si_value.sival_int; signals &= ~mask | set; if (set == SIGNAL_ORDER_BARRIER) { sigemptyset(&sigusr2_mask); sigaddset(&sigusr2_mask, SIGUSR2); if (sigprocmask(SIG_BLOCK, &sigusr2_mask, NULL)) eprintf("sigprocmask:"); } } #endif void install_signal_handlers(void) { #ifdef WINDOWS if (signal(SIGINT, &sigexit) == SIG_ERR) eprintf("signal SIGINT :"); if (signal(SIGTERM, &sigexit) == SIG_ERR) eprintf("signal SIGTERM :"); #else struct sigaction sigact; sigset_t sigset; memset(&sigact, 0, sizeof(sigact)); sigemptyset(&sigset); sigact.sa_mask = sigset; sigact.sa_flags = SA_NODEFER; sigact.sa_handler = &sigexit; if (sigaction(SIGINT, &sigact, NULL)) eprintf("sigaction SIGINT &{.sa_handler=, .sa_mask={}, .sa_flags=SA_NODEFER} NULL:"); if (sigaction(SIGTERM, &sigact, NULL)) eprintf("sigaction SIGTERM &{.sa_handler=, .sa_mask={}, .sa_flags=SA_NODEFER} NULL:"); if (sigaction(SIGQUIT, &sigact, NULL)) eprintf("sigaction SIGQUIT &{.sa_handler=, .sa_mask={}, .sa_flags=SA_NODEFER} NULL:"); sigact.sa_handler = &sigdisable; if (sigaction(SIGUSR1, &sigact, NULL)) eprintf("sigaction SIGUSR1 &{.sa_handler=, .sa_mask={}, .sa_flags=SA_NODEFER} NULL:"); sigact.sa_flags = 0; sigact.sa_handler = SIG_IGN; /* cause child processes (hooks) to be reaped automatically */ if (sigaction(SIGCHLD, &sigact, NULL)) eprintf("sigaction SIGCHLD &{.sa_handler=SIG_IGN, .sa_mask={}, .sa_flags=0} NULL:"); sigact.sa_flags = SA_SIGINFO; sigact.sa_sigaction = &sigipc; if (sigaction(SIGUSR2, &sigact, NULL)) eprintf("sigaction SIGUSR2 &{.sa_sigaction=, .sa_mask={}, .sa_flags=SA_SIGINFO} NULL:"); #endif } #ifndef WINDOWS void install_forceful_exit_signal_handlers(void) { struct sigaction sigact; sigset_t sigset; exiting = 0; memset(&sigact, 0, sizeof(sigact)); sigemptyset(&sigset); sigact.sa_mask = sigset; sigact.sa_flags = 0; sigact.sa_handler = &sigalrm; if (sigaction(SIGINT, &sigact, NULL)) eprintf("sigaction SIGINT &{.sa_handler=, .sa_mask={}, .sa_flags=0} NULL:"); if (sigaction(SIGTERM, &sigact, NULL)) eprintf("sigaction SIGTERM &{.sa_handler=, .sa_mask={}, .sa_flags=0} NULL:"); if (sigaction(SIGQUIT, &sigact, NULL)) eprintf("sigaction SIGQUIT &{.sa_handler=, .sa_mask={}, .sa_flags=0} NULL:"); if (sigaction(SIGALRM, &sigact, NULL)) eprintf("sigaction SIGALRM &{.sa_handler=, .sa_mask={}, .sa_flags=0} NULL:"); } #endif