Reputation: 11
I have tried this code.
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<signal.h>
void sighandler(int);
int main()
{
signal(SIGINT, &sighandler);
while(1)
{
sleep(1);
}
return(0);
}
void sighandler(int signum)
{
printf("Caught signal %d, coming out...\n", signum);
exit(1);
}
But when I press ctrl+c, it doesn't catch the signal. But when I make it run in background and send the SIGINT signal using kill command, it is working properly. Please help me anyone....
Upvotes: 1
Views: 1331
Reputation: 471
I remember reading that sigaction
is the preferred function to use instead of signal
, which is not as portable (pretty sure it was from The Linux Programming Interface which is an essential reference in my opinion).
My first thought was that Ctrl+C might not send the SIGINT
signal if the system is not POSIX compliant, so I made a test program to see what relevant signals I can raise. The answer by @Potatoswatter popped up while I was trying this out and it seem more relevant to your immediate question of not getting output. Regardless, here is a POSIX friendly source file to test four signals (SIGINT
, SIGTERM
, SIGTSTP
, and SIGQUIT
):
#define _POSIX_C_SOURCE 200809L
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
void sigHandler(int sig);
static int did_catch = 0;
static int sig_caught = 0;
int main() {
struct sigaction sa;
/* buidl sigaction struct */
sa.sa_handler = sigHandler;
if (sigemptyset(&sa.sa_mask) != 0) { perror("\nsigemptyset"); exit(EXIT_FAILURE); }
sa.sa_flags = 0;
/* handle signals */
if (sigaction(SIGINT, &sa, NULL) != 0) { perror("\nproblem adding SIGINT"); exit(EXIT_FAILURE); }
if (sigaction(SIGTERM, &sa, NULL) != 0) { perror("\nproblem adding SIGTERM"); exit(EXIT_FAILURE); }
if (sigaction(SIGQUIT, &sa, NULL) != 0) { perror("\nproblem adding SIGQUIT"); exit(EXIT_FAILURE); }
if (sigaction(SIGTSTP, &sa, NULL) != 0) { perror("\nproblem adding SIGTSTP"); exit(EXIT_FAILURE); }
/* wait for signal */
while (!did_catch) {
pause();
}
/* check caught signals */
if (sig_caught == SIGINT) printf("\nsignal is SIGINT\n");
else if (sig_caught == SIGTERM) printf("\nsignal is SIGTERM\n");
else if (sig_caught == SIGQUIT) printf("\nsignal is SIGQUIT\n");
else if (sig_caught == SIGTSTP) printf("\nsignal is SIGTSTP\n");
else printf("\nsignal captured is not listed\n");
return 0;
}
void sigHandler(int sig) {
sig_caught = sig;
did_catch = 1;
}
Hope this helps.
Upvotes: 0
Reputation: 137960
printf
and exit
aren't safe to call inside a signal handler. See signal(7) for the limited things you can do.
The immediate cause of your program's malfunction is likely that the file buffer for stdout
didn't get flushed.
This change should fix it:
void sighandler(int signum)
{
char msg[] = "Caught signal, coming out...\n";
write( STDOUT_FILENO, msg, sizeof msg );
_exit(1); // Do not call atexit routines.
}
However, the better strategy is to avoid doing any real work inside the handler at all. Just set a flag and return.
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<signal.h>
void sighandler(int);
volatile sig_atomic_t gotsig = 0;
volatile sig_atomic_t signum;
int main()
{
signal(SIGINT, &sighandler);
while(!gotsig)
{
sleep(1);
}
printf("Caught signal %d, coming out...\n", signum);
exit(1);
}
void sighandler(int in_signum)
{
gotsig = 1;
signum = in_signum;
}
Upvotes: 1