Signals - c99 vs gnu99 - c

I have the following code. When I compile it with the gnu extensions (-std=gnu99), the program will catch 5 SIGINT before ending (which I would expect). When compiled without it (-std=c99) ends after the second (and only outputs one line).
What am I missing?
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
int int_stage = 0;
int got_signal = 0;
void sigint(int parameter)
{
(void)parameter;
got_signal = 1;
int_stage++;
}
int main()
{
signal(SIGINT,sigint);
while(1)
{
if (got_signal)
{
got_signal = 0;
puts("still alive");
if (int_stage >= 5) exit(1);
}
}
return 0;
}

Use sigaction(2) rather than signal(2).
The Linux man page has this, in particular, in the Portability section:
In the original UNIX systems, when a handler that was established using signal() was invoked by the
delivery of a signal, the disposition of the signal would be reset to SIG_DFL, and the system did
not block delivery of further instances of the signal. System V also provides these semantics for
signal(). This was bad because the signal might be delivered again before the handler had a chance
to reestablish itself. Furthermore, rapid deliveries of the same signal could result in recursive
invocations of the handler.
BSD improved on this situation by changing the semantics of signal handling (but, unfortunately,
silently changed the semantics when establishing a handler with signal()). On BSD, when a signal
handler is invoked, the signal disposition is not reset, and further instances of the signal are
blocked from being delivered while the handler is executing.
The situation on Linux is as follows:
The kernel's signal() system call provides System V semantics.
By default, in glibc 2 and later, the signal() wrapper function does not invoke the kernel system
call. Instead, it calls sigaction(2) using flags that supply BSD semantics. This default behav‐
ior is provided as long as the _BSD_SOURCE feature test macro is defined. By default, _BSD_SOURCE
is defined; it is also implicitly defined if one defines _GNU_SOURCE, and can of course be explic‐
itly defined.
On glibc 2 and later, if the _BSD_SOURCE feature test macro is not defined, then signal() provides
System V semantics. (The default implicit definition of _BSD_SOURCE is not provided if one
invokes gcc(1) in one of its standard modes (-std=xxx or -ansi) or defines various other feature
test macros such as _POSIX_SOURCE, _XOPEN_SOURCE, or _SVID_SOURCE; see feature_test_macros(7).)
Using std=gnu99, you're getting BSD semantics. Using -std=c99, you're getting System V semantics. So the signal handler is "reinstalled" in one case (BSD), and the signal disposition is reset back to SIG_DFL in the other (System V).

The problem is that signal also resets the signal handling mechanism, you have to reset sigint as the signal handler. From the manual
In the original UNIX systems, when a handler that was established using signal() was invoked by the delivery of a signal, the disposition of the signal would be reset to SIG_DFL, and the system did not block delivery of further instances of the signal. System V also provides these semantics for signal(). This was bad because the signal might be delivered again before the handler had a chance to reestablish itself. Furthermore, rapid deliveries of the same signal could result in recursive invocations of the handler.
This is how to do it with the old antiquated signal() call.
Note how int_stage and got_signal have to be sig_atomic_t.
You can also only call async safe functions, look at here for a list.
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
sig_atomic_t int_stage = 0;
sig_atomic_t got_signal = 0;
void sigint(int parameter)
{
(void)parameter;
got_signal = 1;
int_stage++;
}
int main()
{
signal(SIGINT,sigint);
while(1)
{
if (got_signal)
{
signal(SIGINT,sigint);
got_signal = 0;
puts("still alive");
if (int_stage >= 5) exit(1);
}
}
return 0;
}
Please consider either using sigaction, or sigwait.
Sigaction would have practically the same idea, but no nonsense with re-initializing the signal handler. Sigwait would stop your thread until a signal is received. So, for sigwait, you can call any function or deal with any data. I can show you example code if you desire.

I agree with Ethan Steinberg - the "busy wait" is So Wrong...
But the problem is that you're failing to reset the signal handler. AFAIK, you must do this (call "signal(SIGINT,sigint)" again) with any version of C.

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().

Why i am getting continuous SIGSEGV in the below C code

I am trying to learn Signals. I know invalid memory access will cause segfault. So, I register a signal handler for SIGSEGV signal.
#include <stdio.h>
#include <signal.h>
void sighandler(int signum)
{
printf("%s\n", __func__);
}
int main()
{
int *a = NULL;
signal(SIGSEGV, sighandler);
*a = 5;
return 0;
}
Running this code, I am continuously getting SIGSEGV Signals. I thought i should only get the signal once. Can you guys explain why I am getting signals continuously
After the SEGV handler finishes, the instruction that triggered re-executes. Since you didn't do anything to prevent the next execution from faulting, you get SEGV again, ad infinitum.
See more in this answer.
The signal handler is returning to instruction that triggered it namely *a = 5 which is causing it to loop.
You have several problems including the use of printf inside a signal handler.
There are safe and not-safe ways of dealing with this
NOTES
Using signal(2) is not recommended for signal handling in general.
Handling SIGSEGV is even more complicated because of the way the signal semantics work. Quoting from the man page:
The only portable use of signal() is to set a signal's disposition to SIG_DFL or SIG_IGN. The semantics when using signal()
to establish a signal handler vary across
systems (and POSIX.1 explicitly permits this variation); do not use it for this purpose.
POSIX.1 solved the portability mess by specifying sigaction(2), which provides explicit control of the semantics when a
signal handler is invoked; use that interface instead of signal().
So the first thing you should do is use sigaction.
Next, handling SIGSEGV is a weird beast:
How to write a signal handler to catch SIGSEGV?
and
Does linux allow any system call to be made from signal handlers?
have good answers and get into specific details. There are external links in some of the answers given there.
How to do this using signal(2)
Well :-) let's say you want to use signal(2) and you want to play with this in a weird way....
You can use sigjmpset and siglongjmp.
sigjmpset marks a point where siglongjmp should jump to. The first time sigjmpset is called (to set the point) it returns 0. When siglongjmp jumps to it, (which means it gets called again as a result of the long jump), it returns 1.
Which means we can do this:
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <setjmp.h>
sigjmp_buf env;
int sigsav;
void sighandler(int signum)
{
const char msg[] = "Skipping signal\n";
write(2, msg, sizeof(msg));
siglongjmp(env, sigsav);
}
int main()
{
int *a = NULL;
signal(SIGSEGV, sighandler);
if(!sigsetjmp(env, sigsav)) {
printf("setting value of a\n");
*a = 5;
}
else {
printf("returned to sigsetjmp, but now we skip it!\n");
}
return 0;
}

how to alternate continously Signal handler

I want to write a program in c for linux that catchs the first SIGUSR1 signal, ignores the second one and continue in this behaviour (catch-ignore) for the successive SIGUSR1 signals.
I wonder how to keep alternating between the two handlers, because once i set the handler to SIG_IGN, the signal will be ignored and I won't be able to detect it and act accordingly.
This is the code i have tried:
int tst;
void sigusr1_handler(){
if(tst==0){
signal(SIGUSR1,SIG_IGN);
tst=1;
}
else tst= 0;
}
int main(){
signal(SIGUSR1, sigusr1_handler);
tst=1;
while(1){}
return 0;
}
You do not.
What you can do, is have your signal handler decide whether to do something or not -- for example, whether to call an another function or not. This is not completely reliable, however, because standard POSIX signals like SIGUSR1 are not queued. If two or more signals are sent at (nearly) the same time, only one is actually delivered. POSIX realtime signals (SIGRTMIN+0 to SIGRTMAX-0 -- from the programmer's point of view, only the number and semantics differ) are queued, but even they can be dropped in some situations.
In all cases, remember that a signal handler function can only use async-signal safe functions. If you need to be able to use all functions, you should instead block the signals in all threads, and have a dedicated thread receive the signals using e.g. sigwaitinfo(). In this case, you don't have signal handler functions, but instead a dedicated thread that receives the signals, and is thus free to use any functions it wants.
If we reword the question into "How do I alternate the handling of a delivered signal in a single-threaded program?", the answer is simple: you use a volatile sig_atomic_t counter.
For alternating between two choices, do_something_odd() first:
#include <signal.h>
void my_signal_handler(int signum)
{
static volatile sig_atomic_t count = 0;
switch (++count) {
case 1:
do_something_odd();
break;
default:
count = 0;
do_something_even();
break;
}
}
For alternating between three cases, you add more case statements as necessary:
#include <signal.h>
void my_signal_handler(int signum)
{
static volatile sig_atomic_t count = 0;
switch (++count) {
case 2:
do_something_2_of_3();
break;
case 1:
do_something_1_of_3();
break;
default:
count = 0;
do_something_3_of_3()
break;
}
}
The above assumes you install the signal handler using sigaction() without SA_SIGINFO in .sa_flags.
The POSIX standard says you can do up to 128 cases (as sig_atomic_t is guaranteed to be able to represent values 0 to 127, inclusive) this way.
You can do larger sets using an unsigned int or unsigned long, but then you must NOT have SA_NODEFER in the .sa_flags, and if the same handler is used for multiple signals, the .sa_mask must have all the other signals handled by the same handler set. This ensures that the signal handler is not interrupted by another signal that is delivered to the same handler, and allows us to use non-atomic counter variable.
In a multithreaded program one must rely on compiler-provided atomic operations, either legacy __sync built-ins, or __atomic built-ins. They are not GCC-specific; at least Intel Compiler Collection and clang provide them also. For alternating between two options, our = __atomic_xor_fetch(&counter, 1, __ATOMIC_SEQ_CST); or our = __sync_xor_and_fetch(&counter, 1); can be used to obtain and flip a counter between 0 and 1 atomically. For a non-power-of-two number of options, a compare-and-swap loop is typically used.

signal always ends program

Doing homework with signals and fork and have a problem with the signal.
I've created the function:
void trata_sinal_int() {
char op[2];
printf("\nTerminate? (y/n)\n");
scanf("%s", op);
if (op[0] == 'y') {
printf("Bye Bye\n");
exit(0);
}
}
And in main I have:
signal(SIGINT, trata_sinal_int);
When I run this, and press CTRL ^C the function void trata_sinal_int() is called and I got the message.
If I press y program ends as expected but if I press n program still ends.
It is not returning to were he was before pressing CTRL ^C.
Is this supposed to happen?
It depends on which standard you are adhering to, but Standard C doesn't allow you to do much more than modify a variable of type volatile sig_atomic_t or call _Exit (or abort() or signal()) from a signal handler. POSIX is a lot more lenient. Your code in your signal handler, replete with user interaction, is pushing beyond the limits of what even POSIX allows. Normally, you want your signal handler function to be small and svelte.
Note that the signal handler function should be:
void trata_sinal_int(int signum)
{
This allows you to compile without casts or compiler warnings about type mismatches.
The signal() function may reset the signal handler back to default behaviour when it is invoked; classically, it is necessary to reinstate the signal handler inside the signal handler:
signal(signum, trata_sinal_int);
So far, that's all pretty generic and semi-trivial.
When you type the Control-C, the system does go back to roughly where it was when the signal was originally received. However, what happens next depends on where it was (one of the reasons you have to be so very careful inside the handler). For example, if it was in the middle of manipulating the free list pointers inside malloc(), it would return there, but if you'd reinvoked malloc() inside the handler, all hell might be breaking loose. If you were inside a system call, then your call may be interrupted (return with an error indication and errno == EINTR), or it may resume where it left off. Otherwise, it should go back to where the calculation was running.
Here's (a fixed up version of) your code built into a test rig. The pause() function waits for a signal before returning.
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
static void trata_sinal_int(int signum)
{
char op[2];
signal(signum, trata_sinal_int);
printf("\nTerminate? (y/n)\n");
scanf("%s", op);
if (op[0] == 'y')
{
printf("Bye Bye\n");
exit(0);
}
}
int main(void)
{
signal(SIGINT, trata_sinal_int);
for (int i = 0; i < 3; i++)
{
printf("Pausing\n");
pause();
printf("Continuing\n");
}
printf("Exiting\n");
return(0);
}
I should really point out that the scanf() is not very safe at all; a buffer of size 2 is an open invitation to buffer overflow. I'm also not error checking system calls.
I tested on Mac OS X 10.7.5, a BSD derivative. The chance are good that the resetting of signal() would be unnecessary on this platform, because BSD introduced 'reliable signals' a long time ago (pre-POSIX).
ISO/IEC 9899:2011 §7.14.1.1 The signal function
¶5 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.
Furthermore, if such a call to the signal function results in a SIG_ERR return, the
value of errno is indeterminate.252)
252) If any signal is generated by an asynchronous signal handler, the behavior is undefined.
The references to quick_exit() are new in C2011; they were not present in C1999.
POSIX 2008
The section on Signal Concepts goes through what is and is not allowed inside a signal handler under POSIX in considerable detail.
First, your signal handler is not exactly async signal safe. In practice this is probably not a problem in your case, since I assume the main() is basically doing nothing while it is waiting for the signal. But it is definately not correct anyway.
As for why the program exits, not counting segfault:s in the signal handler due to invalid use of FILE* functions such as printf, sscanf etc, when the signal is received any system calls you are doing (or, well, most) will be interreupted with EAGAIN.
If you are using something like sleep() in main to wait for the signal to occur it will be interrupted. You are expected to restart it manually.
To avoid this you probably want to use the significantly more portable sigaction interface instead of signal. If nothing else this allows you to indicate that you want system calls to be restarted.
The reason that FILE * functions (and most other functions that use global state such as malloc and free) is not allowed in signal handlers is that you might be in the middle of another operation on the same state when the signal arrives.
This can cause segfaults or other undefined operations.
The normal 'trick' to implement this is to have a self-pipe: The signal handler will write a byte to the pipe, and your main loop will see this (usually by waiting in poll or something similar) and then act on it.
If you absolutely want to do user interaction in the signal handler you have to use write() and read(), not the FILE* functions.

The Unreliable Signal API - Code doesnt work as expected

Basically,expected output of is that it catches KeyboardInterrupt 5 times and exits the 6th time.(If 1st line of handler() is un-commented)
Now, if i comment that line too, then
also the behavior of program doesnt
change even though I am using
unreliable API.
As I have used signal() function, this is unreliable bcos after the first call to the handler(), SIGINT will then have the default behavior, thats is of exiting the a.out..
The program still quits after 5 ^C.. WHY?
**
The code works even without
reinstating the handler(). WHy?
**
/* ursig1.c */
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
static int count = 0;
void handler(int signo) {
// signal(SIGINT,handler);
/* Re-instate handler */
++count;
/* Increment count */
write(1,"Got SIGINT\n",11); /* Write message */
}
int
main(int argc,char **argv) {
signal(SIGINT,handler);
/* Register function */
while ( count < 5 ) {
puts("Waiting for SIGINT..");
sleep(4);
/* Snooze */
}
puts("End.");
return 0;
}
Have a read of the Linux man page for signal(2), under the section Portability, where it discusses the varying behaviour of signal(2) across the many different versions of Unix. In particular,
In the original Unix systems, when a
handler that was established using
signal() was invoked by the
delivery of a signal, the disposition
of the signal would be reset to
SIG_DFL, and the system did not
block delivery of further instances
of the signal. System V also provides
these semantics for signal().
This is the behaviour you are expecting, but it is not what Linux provides, as allowed by POSIX.1. You should be using sigaction(2) to install your signal handlers to get portable and defined behaviour.

Resources