Set a custom function as handler to all signals - c

I have this assignment to do:
Write a function void myfunct(void(*f)(int sig)) which sets f as handler to all the possible signals.
I have two problems:
How can a get all the possible signals? Is there a function for this? Can I iterate through them in some way?
Will it really work to set the function f as handler given that it takes a parameter? Shouldn't it not have any parameters?
Thank you.

I would personally instead iterate over a static list of signal numbers, and use preprocessor directives to detect which ones are supported (at compile time). For example:
#include <signal.h>
static const all_signals[] = {
#ifdef SIGHUP
SIGHUP, /* POSIX.1 */
#endif
#ifdef SIGQUIT
SIGQUIT, /* POSIX.1 */
#endif
#ifdef SIGTRAP
SIGTRAP, /* POSIX.1 */
#endif
#ifdef SIGIO
SIGIO, /* BSD/Linux */
#endif
/*
* Other signal names omitted for brevity
*/
/* C89/C99/C11 standard signals: */
SIGABRT,
SIGFPE,
SIGILL,
SIGINT,
SIGSEGV,
/* SIGTERM (C89/C99/C11) is also the terminating signal number */
SIGTERM
};
with SIGTERM being the last entry in the array for which a signal handler is installed:
struct sigaction act;
int i = 0;
memset(&act, 0, sizeof act);
sigemptyset(&act.sa_mask);
act.sa_handler = your_signal_handler;
act.sa_flags = 0;
do {
if (sigaction(all_signals[i], &act, NULL)) {
fprintf(stderr, "Cannot install signal %d handler: %s.\n", all_signals[i], strerror(errno));
exit(EXIT_FAILURE);
}
} while (all_signals[i++] != SIGTERM);
This way your code does not require POSIX etc. support to work, but does support POSIX signals if available at compile time.
You can check the Wikipedia Unix signal article and man 7 signal for known signal names.
You can also install the signal handler for POSIX realtime signals using
#if SIGRTMAX-0 > SIGRTMIN-0
for (i = SIGRTMIN; i <= SIGRTMAX; i++)
if (sigaction(i, &act, NULL)) {
fprintf(stderr, "Cannot install realtime signal %d handler: %s.\n", i, strerror(errno));
exit(EXIT_FAILURE);
}
#endif

How can a get all the possible signals? Is there a function for this? Can I iterate through them in some way?
Most implementation provide a constant such as NSIG (Glibc provides NSIG) or _NSIG (Linux provides _NSIG). So, you can loop through that constant and set the same signal handling function for all of them.
There's no POSIX defined value for "highest signal number". There's been a proposal in POSIX to add a macro NSIG_MAX.
{NSIG_MAX}
Maximum possible return value of sysconf(_SC_NSIG). See [cross-ref to XSH sysconf()]. The value of {NSIG_MAX} shall be no greater than the number of signals that the sigset_t type (see [cross-ref to ]) is capable of representing, ignoring any restrictions imposed by sigfillset() or sigaddset().
But it hasn't made it to POSIX yet (most probably it'll a part of the POSIX version - issue 8).
Will it really work to set the function f as handler given that it takes a parameter? Shouldn't it not have any parameters?
The parameter that the signal handling function takes doesn't matter when you are setting a signal disposition. It takes the signal number but that doesn't prevent you from using it as a handler for multiple signals.
But there are special cases you need to handle. Certain signals that can't caught or ignored (SIGKILL and SIGSTOP). There are other signals (SIGFPE, SIGILL and SIGSEGV) for which, while allowed to caught, the signal handler can't return to its caller (i.e. you need exit from the signal handler).

1. How can a get all the possible signals? Is there a function for this? Can I iterate through them in some way?
Seems like there isn't a standardized list you can iterate, but we actually don't need such a list for your task. Signal numbers are always positive and at most SIGRTMAX. In between 1 and SIGRTMAX there might be some numbers that do not correspond to any signal, but you can still try to set a handler for these. From the posix specification of sigaction(sig, ...) (emphasis mine):
RETURN VALUE
Upon successful completion, sigaction() shall return 0; otherwise, -1 shall be returned, errno shall be set to indicate the error, and no new signal-catching function shall be installed.
ERRORS
The sigaction() function shall fail if:
[EINVAL]
The sig argument is not a valid signal number or an attempt is made to catch a signal that cannot be caught or ignore a signal that cannot be ignored.
So it is perfectly fine to call sigaction(123, ...) where 123 is not a signal.
2. Will it really work to set the function f as handler given that it takes a parameter? Shouldn't it not have any parameters?
Why do you think it should have no parameters?
Again, from the posix specification of sigaction():
Member Type
Member Name
Description
void(*) (int)
sa_handler
Pointer to a signal-catching function
The signal handler is supposed to have an int parameter, just like your function f has, so there is no problem.
Putting everything together
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
struct sigaction siga;
void f(int sig) {
printf("Caught signal %d\n", sig);
}
// sets f as handler to all the possible signals.
void myfunct(void(*f)(int sig)) {
siga.sa_handler = f;
for (int sig = 1; sig <= SIGRTMAX; ++sig) {
// this might return -1 and set errno, but we don't care
sigaction(sig, &siga, NULL);
}
}
int main() {
myfunct(f);
pause(); // wait for signal
return 0;
}

Related

Why is my signal handler not working when I send two sigint signals Ctrl-C?

I'm learning to write a signal handler in C for a Linux system. Here's my code:
#include<stdio.h>
#include<signal.h>
#include<unistd.h>
void sig_handler(int signum){
//Return type of the handler function should be void
printf("\nInside handler function\n");
}
int main(){
signal(SIGINT,sig_handler); // Register signal handler
for(int i=1;;i++){ //Infinite loop
printf("%d : Inside main function\n",i);
sleep(1); // Delay for 1 second
}
return 0;
}
My question is, why when I hit Ctrl+C twice, the program stops? Shouldn't it be that everytime I hit Ctrl+C the signal handler runs, so effectively the program should run forever?
In reality, this is my output, the signal handler is only called in the first Ctrl+C, not the second time:
1 : Inside main function
2 : Inside main function
3 : Inside main function
4 : Inside main function
^C
Inside handler function
5 : Inside main function
6 : Inside main function
7 : Inside main function
8 : Inside main function
9 : Inside main function
10 : Inside main function
^C
On Linux, a number of factors contribute to the behaviour of signal. Depending on the version of glibc, the defined feature_test_macros(7), and whether or not the kernel version of the function is used, the results will differ between two polarizing behaviours, described as System V semantics and BSD semantics:
With System V semantics, when a signal handler is invoked, the disposition of the signal is reset to its default behaviour (SIG_DFL). Additionally, further delivery of the signal is not blocked during the execution of the signal handler.
With BSD semantics, when a signal handler is invoked, the disposition of the signal is not reset, and further delivery of the signal is blocked during the execution of the signal handler. Additionally, certain system calls will be automatically be restarted if interrupted by the signal handler.
Your version of signal appears to be supplying System V semantics. The signal disposition is reset after the first signal handler, and the following SIGINT terminates the program.
See signal(2) and its notes on portability for more details.
See signal-safety(7) for a list of functions that are safe to call from within a signal handler. printf is not an async-signal-safe function, and should not be called from within a signal handler.
Use write(2) instead.
The quickest fix is to call signal within the signal handler to once again set the signal disposition to the signal handler.
void sig_handler(int signum)
{
(void) signum;
char msg[] = "Signal handler called!\n";
write(STDOUT_FILENO, msg, strlen(msg));
signal(SIGINT, sig_handler);
}
The more robust solution is to use sigaction(2) to establish signal handlers, as its behaviour is more consistent and provides better portability.
A basic example:
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
volatile sig_atomic_t sig_count = 0;
void sig_handler(int signum)
{
(void) signum;
sig_count++;
char msg[] = "Signal handler called!\n";
write(STDOUT_FILENO, msg, strlen(msg));
}
int main(void)
{
struct sigaction sa = { .sa_handler = sig_handler };
sigaction(SIGINT, &sa, NULL);
while (sig_count < 5);
}
The default behaviour of sigaction is similar to that described by BSD semantics, with the exception that certain system calls will not restart when interrupted by the signal handler.
To enable this behaviour, the .sa_flags member of the struct sigaction should contain the SA_RESTART flag.
To mimic System V semantics, the .sa_flags member of the struct sigaction should contain the SA_RESETHAND and SA_NODEFER flags.
TL;DR: use sigaction(), not signal(), to install signal handlers.
As comments and other answers have observed, your signal handler has undefined behavior as a result of its call to printf(). In the event that the signal handler is ever triggered, that gives the whole program UB, which makes it very difficult to reason about its observed behavior.
But consider this variation instead:
#include<stdio.h>
#include<signal.h>
#include<unistd.h>
void sig_handler(int signum){
static const char msg[] = "\nInside handler function\n";
write(1, msg, sizeof(msg) - 1);
}
int main(){
signal(SIGINT,sig_handler); // Register signal handler
for(int i=1;;i++){ //Infinite loop
printf("%d : Inside main function\n",i);
sleep(1); // Delay for 1 second
}
return 0;
}
I have switched from printf to write inside the signal handler, thereby removing the UB. And if I compile it with
gcc -std=c11 htest.c -o htest
then the resulting executable still exhibits the behavior you describe: the first Ctrl-C is handled, but the second is not.
HOWEVER, if I instead compile with
gcc htest.c -o htest
then the resulting program intercepts every Ctrl-C I type, as I guess you were expecting. So what's going on?
The problem revolves around the fact that the details of the behavior of the signal() function have varied historically. For more detail, see the portability notes in the signal(2) manual page, but here's a brief rundown:
In the original System V UNIX, the custom signal handlers installed via signal() were one-shots: when such a handler was triggered, the disposition for the signal was reset to its default, and the signal was not blocked during execution of the handler.
The System V behavior has some issues, so BSD implemented signal() differently in these respects: signal disposition is not automatically reset, and the signal is blocked during execution of the handler. And additionally, in BSD, certain blocking system calls are automatically restarted if interrupted by a signal that does not result in the program terminating.
These differences mean that the only portable uses for the signal() function are for setting signal disposition to SIG_DFL or SIG_IGN.
Glibc supports both alternatives, and which one you get is controlled by feature test macros, which can be influenced by compiler command-line options. It defaults to BSD semantics as long as the _DEFAULT_SOURCE macro is defined (_BSD_SOURCE prior to glibc 2.19). Gcc defines that macro by default, but some command line options, notably the strict-conformance -std options, cause Gcc not to define it. And that's why I could get different behavior depending on how I compiled the program.
On POSIX systems, the solution is to use the sigaction() function instead of signal() to register signal handlers. This function has well-defined semantics for all the areas of behavioral difference described above, including a well-defined means to choose among them. However, to get its declaration included in all cases, you will need to ensure that a different feature-test macro is defined. For example:
// Manipulation of feature-test macros should precede all header inclusions
#ifndef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 1
#endif
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
void sig_handler(int signum) {
static const char msg[] = "\nInside handler function\n";
write(1, msg, sizeof(msg) - 1);
}
int main(void) {
// Register signal handler
struct sigaction sa = { .sa_handler = sig_handler /* default sa_mask and sa_flags */ };
sigaction(SIGINT, &sa, NULL);
while (int i = 1; ; i++) {
printf("%d : Inside main function\n",i);
sleep(1);
}
return 0;
}
That will reliably get you a handler that is not reset when triggered, does have SIGINT blocked while it is being handled, and does not automatically restart system calls interrupted by the signal. That will prevent the program from being killed via a SIGINT, though there are other ways it can be killed, such as via a SIGKILL (which cannot be blocked or handled).
My question is, why when I hit Ctrl+C twice, the program stops?
Undefined behaviour:
Your code invokes undefined behaviour because it calls a function (printf) that isn't async-signal-safe.¹
From C11:
If the signal occurs other than as the result of calling the abort or
raise function, the behavior is undefined if the signal handler refers
to any object with static or thread storage duration that is not a
lock-free atomic object other than by assigning a value to an object
declared as volatile sig_atomic_t, or the signal handler calls any
function in the standard library other than the abort function, the
_Exit function, the quick_exit function, or the signal function with the first argument equal to the signal number corresponding to the
signal that caused the invocation of the handler.
As per the C Standard, you can only call:
abort()
_Exit()
quick_exit()
signal() /* With the first argument equal to the signal number the handler caught */
safely inside a signal handler.
The POSIX standard, however, specifies many more functions. So you can have write(), but not printf().
[1] — An async-signal-safe function is one that can be safely called from within a signal handler. (Linux man page)
Don't use signal(). Instead use sigaction().
Per the spec, [w]hen a signal occurs, and [the second argument to signal] points to a function, it is implementation-defined whether the equivalent of a
signal(sig, SIG_DFL); is executed...
Historically, some UNIX flavors reset the signal disposition to the default behavior upon entry into the user-defined signal handler. That meant that your first SIGFOO would invoke your handler, but your next one would trigger SIG_DFL behavior. Importantly, this is consistent with what you observe.
Yes, printf() is unsafe (undefined behavior) to call in a signal handler. In the code you provide, it might conceivably interrupt itself, which can lead to all sorts of nastiness. In practice, people call printf() all the time in trivial programs to no great harm. The fact that your behavior is repeatable suggests that you are getting deterministic behavior, and not dreadful eldritch magic undefined behavior.
sigaction() forces you to specify what kind of behavior you want when the user-supplied handler is invoked, and is thus superior to signal().

Linux does not implement POSIX signal queuing?

The POSIX article for sigaction states:
If SA_SIGINFO is set in sa_flags, then subsequent occurrences of sig
generated by sigqueue() or as a result of any signal-generating
function that supports the specification of an application-defined
value (when sig is already pending) shall be queued in FIFO order
until delivered or accepted; the signal-catching function shall be
invoked with three arguments. The application specified value is
passed to the signal-catching function as the si_value member of the
siginfo_t structure.
This says nothing about merging of occurrences of the same signal (signo). And even if it meant merging, then the phrase about FIFO would be incomplete. For example, if the FIFO is [SIGALRM, SIGIO, SIGUSR1, SIGIO], what would it be after merging, [SIGALRM, SIGIO, SIGUSR1] or [SIGALRM, SIGUSR1, SIGIO]?
However, I saw several reports (0, 1, 2) that Linux indeed merges occurrences of the same signal. I also wrote a small test program that confirms that occurrences of the same signal sent with sigqueue when that signal is blocked are merged on ArchLinux. A signal handler was installed with sigaction.
Linux [skipped] 5.3.8-arch1-1 #1 SMP PREEMPT [skipped] x86_64 GNU/Linux
If occurrences of the same signal are merged, then transmitting information via union sigval does not make sense because this information may be unpredictably lost.
Is my understanding of POSIX incorrect, or is Linux implementing it incorrectly?
[Update 2019-11-09 09:51:32+00:00. I found another chunk of documentation that corroborates my point. According to the article “2. General Information”,
If a subsequent occurrence of a pending signal is generated, it is
implementation-defined as to whether the signal is delivered or
accepted more than once in circumstances other than those in which
queuing is required.
and another one on sigqueue,
If SA_SIGINFO is set for signo and if the resources were available to
queue the signal, the signal shall be queued and sent to the receiving
process.
The sigqueue() function shall fail if:
[EAGAIN]
No resources are available to queue the signal. The process has already queued {SIGQUEUE_MAX} signals that are still pending at the
receiver(s), or a system-wide resource limit has been exceeded.
I used sigaction with SA_SIGINFO set and sigqueue. The function sigqueue did not return EAGAIN.]
[Update 2019-11-09 17:45:25+00:00. My test program. The sigprint functions are for printing using write and a statically allocated buffer; they are not important.
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include "sigprint.h"
void signal_handler(int signo, siginfo_t *info, void *context) {
sigprint_string("|");
sigprint_long(info->si_value.sival_int);
sigprint_flush();
}
void sigqueue_check(pid_t pid, int signo, union sigval value) {
if (sigqueue(pid, signo, value) == -1) {
printf(" returned error code %d which is %s to EAGAIN.\n",
errno, errno == EAGAIN ? "==" : "!=");
exit(24);
}
}
int main() {
struct sigaction sigaction0;
union sigval sigval0;
sigset_t sigset0, sigset1;
sigaction0.sa_sigaction = &signal_handler;
sigemptyset(&sigaction0.sa_mask);
sigaction0.sa_flags = SA_SIGINFO | SA_RESTART;
sigaction(SIGALRM, &sigaction0, NULL);
sigemptyset(&sigset0);
sigaddset(&sigset0, SIGALRM);
sigprocmask(SIG_BLOCK, &sigset0, &sigset1);
sigval0.sival_int = 10;
sigqueue_check(getpid(), SIGALRM, sigval0);
sigval0.sival_int = 11;
sigqueue_check(getpid(), SIGALRM, sigval0);
sigval0.sival_int = 12;
sigqueue_check(getpid(), SIGALRM, sigval0);
sigprocmask(SIG_SETMASK, &sigset1, NULL);
sleep(1);
return 0;
}
]
The documented behavior on Linux is to not queue duplicate blocked signals.
From man 7 signal:
Standard signals do not queue. If multiple instances of a standard signal are generated while that signal is blocked, then only one instance of the signal is marked as pending (and the signal will be delivered just once when it is unblocked). In the case where a standard signal is already pending, the siginfo_t structure (see sigaction(2)) associated with that signal is not overwritten on arrival of subsequent instances of the same signal. Thus, the process will receive the information associated with the first instance of the signal.
However... the man page also says:
Multiple instances of real-time signals can be queued. By contrast, if multiple instances of a standard signal are delivered while that signal is currently blocked, then only one instance is queued.
Are you looking at the POSIX documentation for real time signals and testing with standard ones?

Catching non-specific signals in C [duplicate]

What is the best way in C on Linux for setting up a program that can handle multiple POSIX-signals with the same function?
For example in my code I have a handler function that I want to generically call when ever a signal is caught to perform some actions:
/* Exit handler function called by sigaction */
void exitHandler( int sig, siginfo_t *siginfo, void *ignore )
{
printf("*** Got %d signal from %d\n", siginfo->si_signo, siginfo->si_pid);
loopCounter=0;
return;
}
I have set up two signals to catch by having individual sigaction calls for each signal:
/* Set exit handler function for SIGUSR1 , SIGINT (ctrl+c) */
struct sigaction act;
act.sa_flags = SA_SIGINFO;
act.sa_sigaction = exitHandler;
sigaction( SIGUSR1, &act, 0 );
sigaction( SIGINT, &act, 0 );
Is this the correct way to set up this type of handling? Is there any other way where I don't have to enumerate all the possible signal numbers?
I can't see how you can straightforwardly set a single handler for all signals. However, you can get fairly close by using sigfillset() to generate a set containing all valid signal numbers, and then iterate over possible signal numbers using sigismember() to determine whether that number is in the set, and set a handler if so. OK, I can't see a method of determining what the maximum possible signal number is, so you might have to guess a suitable maximum value.
"signum" parameter of "sigaction" system call is an integer value, which does not work as a flag.
As far as I know, there's no way to assign one handler function for several signals in one call.
Is this the correct way to set up this type of handling?
Not quite - it's not safe to use printf() inside a signal handler, but you can still use write() to stdout or stderr.

c setitimer not sending signal when outside its call scope

i have the following case
void foo() {
printf("hi\n");
while(1);
}
int main(void)
{
struct sigaction temp;
temp.sa_handler = &foo;
sigfillset(&temp.sa_mask);
sigdelset(&temp.sa_mask, SIGVTALRM);
sigdelset(&temp.sa_mask, SIGINT );
sigaction(SIGVTALRM, &temp, NULL);
struct itimerval tv;
tv.it_value.tv_sec = 2; /* first time interval, seconds part */
tv.it_value.tv_usec = 0; /* first time interval, microseconds part */
tv.it_interval.tv_sec = 2; /* following time intervals, seconds part */
tv.it_interval.tv_usec = 0; /* following time intervals, microseconds part */
if (setitimer(ITIMER_VIRTUAL, &tv, NULL)){
perror(NULL);
}
while(1);
return 0;
}
all I want is that every 2 seconds foo will be called (foo actually does some other stuff other than while(1), just assume foo run takes more than 2 seconds), after 2 seconds foo is indeed called but then no other call is made untill foo returns. I tried playing with the signal masks (hence the sigfillset) but also when simply calling signal(SIGVTALRM, foo) no changes are made in the result. I also tried having the itimerval and the sigactions variables declared outside main and it didn't quite affect anything.
is the thing I'm trying to do even possible?
thanks!
reference: <http://www.gnu.org/software/libc/manual/html_node/Signals-in-Handler.html>
24.4.4 Signals Arriving While a Handler Runs
What happens if another signal arrives while your signal handler function is running?
When the handler for a particular signal is invoked, that signal is automatically blocked until the handler returns. That means that if two signals of the same kind arrive close together, the second one will be held until the first has been handled. (The handler can explicitly unblock the signal using sigprocmask, if you want to allow more signals of this type to arrive; see Process Signal Mask.)
However, your handler can still be interrupted by delivery of another kind of signal. To avoid this, you can use the sa_mask member of the action structure passed to sigaction to explicitly specify which signals should be blocked while the signal handler runs. These signals are in addition to the signal for which the handler was invoked, and any other signals that are normally blocked by the process. See Blocking for Handler.
When the handler returns, the set of blocked signals is restored to the value it had before the handler ran. So using sigprocmask inside the handler only affects what signals can arrive during the execution of the handler itself, not what signals can arrive once the handler returns.
Portability Note: Always use sigaction to establish a handler for a signal that you expect to receive asynchronously, if you want your program to work properly on System V Unix. On this system, the handling of a signal whose handler was established with signal automatically sets the signal’s action back to SIG_DFL, and the handler must re-establish itself each time it runs. This practice, while inconvenient, does work when signals cannot arrive in succession. However, if another signal can arrive right away, it may arrive before the handler can re-establish itself. Then the second signal would receive the default handling, which could terminate the process.
reference:<http://www.gnu.org/software/libc/manual/html_node/Process-Signal-Mask.html#Process-Signal-Mask>
24.7.3 Process Signal Mask
The collection of signals that are currently blocked is called the signal mask. Each process has its own signal mask. When you create a new process (see Creating a Process), it inherits its parent’s mask. You can block or unblock signals with total flexibility by modifying the signal mask.
The prototype for the sigprocmask function is in signal.h.
Note that you must not use sigprocmask in multi-threaded processes, because each thread has its own signal mask and there is no single process signal mask. According to POSIX, the behavior of sigprocmask in a multi-threaded process is “unspecified”. Instead, use pthread_sigmask.
Function: int sigprocmask (int how, const sigset_t *restrict set, sigset_t *restrict oldset)
Preliminary: | MT-Unsafe race:sigprocmask/bsd(SIG_UNBLOCK) | AS-Unsafe lock/hurd | AC-Unsafe lock/hurd | See POSIX Safety Concepts.
The sigprocmask function is used to examine or change the calling process’s signal mask. The how argument determines how the signal mask is changed, and must be one of the following values:
SIG_BLOCK
Block the signals in set—add them to the existing mask. In other words, the new mask is the union of the existing mask and set.
SIG_UNBLOCK
Unblock the signals in set—remove them from the existing mask.
SIG_SETMASK
Use set for the mask; ignore the previous value of the mask.
The last argument, oldset, is used to return information about the old process signal mask. If you just want to change the mask without looking at it, pass a null pointer as the oldset argument. Similarly, if you want to know what’s in the mask without changing it, pass a null pointer for set (in this case the how argument is not significant). The oldset argument is often used to remember the previous signal mask in order to restore it later. (Since the signal mask is inherited over fork and exec calls, you can’t predict what its contents are when your program starts running.)
If invoking sigprocmask causes any pending signals to be unblocked, at least one of those signals is delivered to the process before sigprocmask returns. The order in which pending signals are delivered is not specified, but you can control the order explicitly by making multiple sigprocmask calls to unblock various signals one at a time.
The sigprocmask function returns 0 if successful, and -1 to indicate an error. The following errno error conditions are defined for this function:
EINVAL
The how argument is invalid.
You can’t block the SIGKILL and SIGSTOP signals, but if the signal set includes these, sigprocmask just ignores them instead of returning an error status.
Remember, too, that blocking program error signals such as SIGFPE leads to undesirable results for signals generated by an actual program error (as opposed to signals sent with raise or kill). This is because your program may be too broken to be able to continue executing to a point where the signal is unblocked again. See Program Error Signals.
I know that this has been answered and accepted already but I made tiny changes to the OP's question as follows in accordance with my comments and had a successful result (foo being called every 2 seconds, ad infinitum)
Note that addition of the memset of the temp variable and the changing from SIGVTALRM to SIGALRM.
#include <stdio.h>
#include <sys/time.h>
void foo() {
printf("hi\n");
}
int main(int argc, char **argv)
{
struct sigaction temp;
memset(&temp, 0, sizeof(temp));
temp.sa_handler = &foo;
sigfillset(&temp.sa_mask);
sigdelset(&temp.sa_mask, SIGALRM);
sigdelset(&temp.sa_mask, SIGINT );
sigaction(SIGALRM, &temp, NULL);
struct itimerval tv;
tv.it_value.tv_sec = 2; /* first time interval, seconds part */
tv.it_value.tv_usec = 0; /* first time interval, microseconds part */
tv.it_interval.tv_sec = 2; /* following time intervals, seconds part */
tv.it_interval.tv_usec = 0; /* following time intervals, microseconds part */
if (setitimer(ITIMER_REAL, &tv, NULL)){
fprintf (stderr, "cannot start timer\n");
perror(NULL);
}
while(1) {
fprintf (stdout, "sleep 1\n");
sleep (1);
}
return 0;
}

Signal handler for all signal

How can I register a signal handler for ALL signal, available on the running OS, using signal(3)?
My code looks like this:
void sig_handler(int signum)
{
printf("Received signal %d\n", signum);
}
int main()
{
signal(ALL_SIGNALS_??, sig_handler);
while (1) {
sleep(1);
};
return 0;
}
Most systems have a macro NSIG or _NSIG (the former would not be available in standards-conformance mode since it violates the namespace) defined in signal.h such that a loop for (i=1; i<_NSIG; i++) will walk all signals. Also, on POSIX systems that have signal masks, CHAR_BIT*sizeof(sigset_t) is an upper bound on the number of signals which you could use as a fallback if neither NSIG nor _NSIG is defined.
Signal handlers have to deal with reentrancy concerns and other problems. In practice, it's often more convenient to mask signals and then retrieve them from time to time. You can mask all signals (except SIGSTOP and SIGKILL, which you can't handle anyway) with this:
sigset_t all_signals;
sigfillset(&all_signals);
sigprocmask(SIG_BLOCK, &all_signals, NULL);
The code is slightly different if you're using pthreads. Call this in every thread, or (preferably) in the main thread before you create any others:
sigset_t all_signals;
sigfillset(&all_signals);
pthread_sigmask(SIG_BLOCK, &all_signals, NULL);
Once you've done that, you should periodically call sigtimedwait(2) like this:
struct timespec no_time = {0, 0};
siginfo_t result;
int rc = sigtimedwait(&all_signals, &result, &no_time);
If there is a signal pending, information about it will be placed in result and rc will be the signal number; if not, rc will be -1 and errno will be EAGAIN. If you're already calling select(2)/poll(2) (e.g. as part of some event-driven system), you may want to create a signalfd(2) instead and attach it to your event loop. In this case, you still need to mask the signals as shown above.

Resources