diff --git a/headers/posix/signal.h b/headers/posix/signal.h index 06c0d7c8e4..4bb3d3ccaf 100644 --- a/headers/posix/signal.h +++ b/headers/posix/signal.h @@ -147,6 +147,7 @@ extern "C" { #endif sighandler_t signal(int sig, sighandler_t signalHandler); +sighandler_t sigset(int sig, sighandler_t signalHandler); int raise(int sig); int kill(pid_t pid, int sig); int send_signal(pid_t tid, unsigned int sig); diff --git a/src/system/libroot/posix/signal/Jamfile b/src/system/libroot/posix/signal/Jamfile index 1e1fc80494..cd84bbb9a3 100644 --- a/src/system/libroot/posix/signal/Jamfile +++ b/src/system/libroot/posix/signal/Jamfile @@ -7,6 +7,7 @@ MergeObject posix_signal.o : killpg.cpp raise.c send_signal.c + set_signal_disposition.cpp set_signal_stack.c sigaction.c sigaltstack.c diff --git a/src/system/libroot/posix/signal/set_signal_disposition.cpp b/src/system/libroot/posix/signal/set_signal_disposition.cpp new file mode 100644 index 0000000000..1954cd38a1 --- /dev/null +++ b/src/system/libroot/posix/signal/set_signal_disposition.cpp @@ -0,0 +1,49 @@ +/* + * Copyright 2007, Vasilis Kaoutsis, kaoutsis@sch.gr + * Distributed under the terms of the MIT License. + */ + + +#include + + +sighandler_t +sigset(int signal, sighandler_t signalHandler) +{ + struct sigaction newAction; + struct sigaction oldAction; + + newAction.sa_handler = signalHandler; + newAction.sa_flags = 0; + if (signal == SIGCHLD && signalHandler == SIG_IGN) { + // In case of SIGCHLD the specification requires SA_NOCLDWAIT behavior. + newAction.sa_flags |= SA_NOCLDWAIT; + } + + sigemptyset(&newAction.sa_mask); + if (sigaction(signal, signalHandler == SIG_HOLD ? NULL : &newAction, + &oldAction) == -1) { + return SIG_ERR; + } + + sigset_t newSet; + sigset_t oldSet; + + sigemptyset(&newSet); + sigaddset(&newSet, signal); + + if (signalHandler == SIG_HOLD) { + if (sigprocmask(SIG_BLOCK, &newSet, &oldSet) == -1) + return SIG_ERR; + } else { + // Disposition is not equal to SIG_HOLD, so sig will be + // removed from the calling process' signal mask. + if (sigprocmask(SIG_UNBLOCK, &newSet, &oldSet) == -1) + return SIG_ERR; + } + + if (sigismember(&oldSet, signal)) + return SIG_HOLD; + else + return oldAction.sa_handler; +}