Reputation: 2230
The following code catches the "SIGINT" signal only once and then interrupts (program exists):
#include <signal.h>
#include <stdio.h>
void IntHandler(int value);
void CatchIntSignal()
{
struct sigaction intAction;
intAction.sa_handler = IntHandler;
sigemptyset(&intAction.sa_mask);
intAction.sa_flags = 0;
//if to uncomment any of "0" or "SIG_IGN" - IntHandler will be never called:
//intAction.sa_sigaction = 0/*SIG_IGN*/;
if(sigaction(SIGINT, &intAction, NULL) != 0)
{
printf("sigaction() failed.\n");
}
}
void IntHandler(int value)
{
printf("IntHandler(%d)\n", value);
//uncommenting this does not help:
//CatchIntSignal();
}
int main()
{
CatchIntSignal();
getchar();
return 0;
}
How must I modify this code to preserve program's exit after SIGINT catching? If to set intAction.sa_sigaction to 0 or to SIG_IGN - IntHandler will never be called - but why? Which undefined value does it have to say system that "it's necessary to call IntHandler"? If I will set some handler to intAction.sa_sigaction - this handler will be called (but IntHandler will not). How does system know that I did set something to intAction.sa_sigaction?
Upvotes: 1
Views: 968
Reputation: 23453
After you have caught the interrupt signal and handled in your catch codes, you need to set the handling back to SIG_DFL
.
EDIT: Ignore please. This is applicable only to the old unix signal().
Upvotes: 0
Reputation: 140866
Your problem is that the sa_handler
and sa_sigaction
fields of struct sigaction
are actually the same field. Quoting the (OSX) manpage for sigaction(2)
:
struct sigaction {
union __sigaction_u __sigaction_u; /* signal handler */
sigset_t sa_mask; /* signal mask to apply */
int sa_flags; /* see signal options below */
};
union __sigaction_u {
void (*__sa_handler)(int);
void (*__sa_sigaction)(int, struct __siginfo *,
void *);
};
#define sa_handler __sigaction_u.__sa_handler
#define sa_sigaction __sigaction_u.__sa_sigaction
So your assignment to sa_sigaction
is overwriting the handler you already set. You should just set sa_handler
and leave sa_sigaction
alone. This is how CatchIntSignal
should read:
void CatchIntSignal()
{
struct sigaction intAction;
intAction.sa_handler = IntHandler;
sigemptyset(&intAction.sa_mask);
intAction.sa_flags = SA_RESTART;
if(sigaction(SIGINT, &intAction, NULL) != 0)
printf("sigaction() failed: %s\n", strerror(errno));
}
(You may need to add #includes of string.h
and errno.h
to get the strerror(errno)
bit to compile. Always include strerror(errno)
in error messages triggered when system calls fail.)
(CORRECTION: added SA_RESTART
to flags per ninjalj.)
Upvotes: 4
Reputation: 755064
Your trouble is probably that the system call is interrupted, so the getchar()
returns, probably with EOF. And the next thing the program does is exit...
So, you could try checking what getchar()
returns, reset the error status on stdin
, and call getchar()
again to get the next signal.
Upvotes: 2