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.
Related
I want to write a C program that runs for a specified amount of seconds
say 10 seconds and then exits. The code should set up an interrupt to go
off after a specified amount of time has elapsed.
Here is my attempt. But I am not sure if SIGALRM is the correct way to do it.
Can SIGALRM be called an interrupt?
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
void handler()
{
_exit(0);
}
int main()
{
signal(SIGALRM, handler);
alarm(10);
for (;;); /* You can assume that for(;;); is just a dummy code. The main idea is to insert something into code. Whatever code it may be so that it stops after 10 seconds – */
return 0;
}
Any suggestions/alternatives/better way to achieve this?
The wording "signal" vs. "interrupt" is not fully clear. Signals can interrupt system calls, so a signal is an interrupt in this sense. But a signal is not a hardware interrupt. Whan you use an operating system, normal programs often don't have direct access to hardware interrupts.
Calling _exit from the signal handler might be problematic if your program needs to finish a task or to clean up something.
I suggest to implement a graceful end by setting a flag. Additionally I suggest to use sigaction instead of signal, because the semantics of signal and signal handlers set up with this function is implementation-dependent.
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
static volatile sig_atomic_t timeout = 0;
void handler(int sig)
{
(void) sig;
timeout = 1;
}
int main(void)
{
struct sigaction act;
memset(&act, 0, sizeof(act));
act.sa_handler = handler;
if(sigaction(SIGALRM, act, NULL) < 0)
{
// handle error
}
alarm(10);
while(!timeout /* and maybe other conditions */)
{
// do something, handle error return codes and errno (EINTR)
// check terminate flag as necessary
}
// clean up if necessary
return 0;
}
Explanation (as requested in a comment)
static volatile sig_atomic_t timeout = 0;
sig_atomic_t is a type that guarantees atomic access even in the presence of asynchronous interrupts made by signals. That means an access to the variable cannot be interrupted in between, i.e. the software will never see a partially modified value. (see https://en.cppreference.com/w/c/program/sig_atomic_t)
volatile informs the compiler not to optimize access to the variable. This is necessary because the signal handler may modify the value while the main function is running the loop that is intended to check the flag. Otherwise the compiler might optimize the access out of the loop condition and do it only once before the loop because the variable is never modified inside the loop. (see https://en.cppreference.com/w/c/language/volatile)
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;
}
I have a server and client codes that IPC with each other via named pipes(FIFO). Client sends SIGNAL(SIGUSR1 for example) to Server and checking to see if any signal arrived with given time resolution(via command line argument). Server checks (if its 5ms) 5ms everytime, checks if any signal arrived after 5ms , if arrived it does some code , if not continues until it catches a signal.
So here is that what my problem lies. I dont know what to use for these kind of action. I looked up "Unix Systems Programming: Communication, Concurrency, and Threads Kay A. Robbins , Steven Robbins" found some functions that might be use for me. Sleep,Alarm,uSleep,NanoSleep,Pause. But i dont know which one to use in my situation. Sleep is out of question i think due it takes seconds and i think it overflows when you try to convert to milliseconds.
A little code snippet or psudocode would be nice to understand for me.
I simply asking how to check if signal arrived in given resolution frequency. I have to check if signal arrived in those milliseconds. Check any given "n" mseconds if signal catched.
I think that the function nanosleep (and also usleep) could work!
You have to install a signal handler for the desired signal that can be catched by the program, e.g.:
#include <signal.h>
/* Handler for the signals */
void my_handler(int signum)
{
if(signum == SIGUSR1) {
/* Perform an action on signal SIGUSR1*/
}
}
int main(int argc, char * argv[]){
/* .... */
/* Install the signal handler to catch the desired signals*/
signal(SIGUSR1, my_handler);
/* .... */
}
You have to loop and wait for a signal. And if you catch a signal you have to perform the actions either inside the handler or using the exception that raise when nanosleep is interrupted.
#include <time.h> /* Contains nanosleep + timespec definition */
#include <errno.h> /* Contains the errno variable and the ERROR_CODE macros */
#include <stdio.h> /* Contains definition of perror */
#include <stdlib.h> /* Contains the exit function */
int main(int argc, char * argv[]){
/* fetch milliseconds from argv and put in a variable named "ms" */
struct timespec interval;
interval.tv_sec = 0; /* Seconds*/
interval.tv_nsec = ms*1e6; /* 10^6 Nanoseconds = 1 millisecond */
struct timespec interrupted;
/* .. */
while(1) {
if(nanosleep(&interval, &interrupted) != 0){
/* The sleeping was interrupted! */
if(errno == EINTR){
//The interruption is due to a signal
}
else {
/*The interruption is due to another cause (read the man page) --> Print an error message */
perror("Nanosleep");
break; /* Exit from main loop */
}
}
return EXIT_FAILURE;
}
Alternatively you can also deal the signals inside the handlers.
Alternative Solution
If you are sure that a signal will ever come and don't need to control each 5 milliseconds you could also use the function pause. In fact the man page says:
pause causes the calling process (or thread) to sleep until a signal
is delivered that either terminates the process or causes the
invocation of a signal-catching function.
In this case you have only to install the signal handler and wait.
Let me know if it answered your question.
Sincerly yours,
Mirko
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.
The example code of section 10.6, the expected result is:
after several iterations, the static structure used by getpwnam will be corrupted, and the program will terminate with SIGSEGV signal.
But on my platform, Fedora 11, gcc (GCC) 4.4.0, the result is
[Langzi#Freedom apue]$ ./corrupt
in sig_alarm
I can see the output from sig_alarm only once, and the program seems hung up for some reason, but it does exist, and still running.
But when I try to use gdb to run the program, it seems OK, I will see the output from sig_alarm at regular intervals.
And from my manual, it said the signal handler will be set to SIG_DEF after the signal is handled, and system will not block the signal. So at the beginning of my signal handler I reset the signal handler.
Maybe I should use sigaction instead, but I only want to know the reason about the difference between normal running and gdb running.
Any advice and help will be appreciated.
following is my code:
#include "apue.h"
#include <pwd.h>
void sig_alarm(int signo);
int main()
{
struct passwd *pwdptr;
signal(SIGALRM, sig_alarm);
alarm(1);
for(;;) {
if ((pwdptr = getpwnam("Zhijin")) == NULL)
err_sys("getpwnam error");
if (strcmp("Zhijin", pwdptr->pw_name) != 0) {
printf("data corrupted, pw_name: %s\n", pwdptr->pw_name);
}
}
}
void sig_alarm(int signo)
{
signal(SIGALRM, sig_alarm);
struct passwd *rootptr;
printf("in sig_alarm\n");
if ((rootptr = getpwnam("root")) == NULL)
err_sys("getpwnam error");
alarm(1);
}
According to the standard, you're really not allowed to do much in a signal handler. All you are guaranteed to be able to do in the signal-handling function, without causing undefined behavior, is to call signal, and to assign a value to a volatile static object of the type sig_atomic_t.
The first few times I ran this program, on Ubuntu Linux, it looked like your call to alarm in the signal handler didn't work, so the loop in main just kept running after the first alarm. When I tried it later, the program ran the signal handler a few times, and then hung. All this is consistent with undefined behavior: the program fails, sometimes, and in various more or less interesting ways.
It is not uncommon for programs that have undefined behavior to work differently in the debugger. The debugger is a different environment, and your program and data could for example be laid out in memory in a different way, so errors can manifest themselves in a different way, or not at all.
I got the program to work by adding a variable:
volatile sig_atomic_t got_interrupt = 0;
And then I changed your signal handler to this very simple one:
void sig_alarm(int signo) {
got_interrupt = 1;
}
And then I inserted the actual work into the infinite loop in main:
if (got_interrupt) {
got_interrupt = 0;
signal(SIGALRM, sig_alarm);
struct passwd *rootptr;
printf("in sig_alarm\n");
if ((rootptr = getpwnam("root")) == NULL)
perror("getpwnam error");
alarm(1);
}
I think the "apue" you mention is the book "Advanced Programming in the UNIX Environment", which I don't have here, so I don't know if the purpose of this example is to show that you shouldn't mess around with things inside of a signal handler, or just that signals can cause problems by interrupting the normal work of the program.
According to the spec, the function getpwnam is not reentrant and is not guaranteed to be thread safe. Since you are accessing the structure in two different threads of control (signal handlers are effectively running in a different thread context), you are running into this issue. Whenever you have concurrent or parallel execution (as when using pthreads or when using a signal handler), you must be sure not to modify shared state (e.g. the structure owned by 'getpwnam'), and if you do, then appropriate locking/synchronization must be used.
Additionally, the signal function has been deprecated in favor of the sigaction function. In order to ensure portable behavior when registering signal handlers, you should always use the sigaction invocation.
Using the sigaction function, you can use the SA_RESETHAND flag to reset the default handler. You can also use the sigprocmask function to enable/disable the delivery of signals without modifying their handlers.
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
void sigalrm_handler(int);
int main()
{
signal(SIGALRM, sigalrm_handler);
alarm(3);
while(1)
{
}
return 0;
}
void sigalrm_handler(int sign)
{
printf("I am alive. Catch the sigalrm %d!\n",sign);
alarm(3);
}
For example, my code is runing in main doing nothing and every 3 seconds my program says im alive x)
I think that if you do as i done calling in the handler function alarm with value 3, the problem is resolved :)