Reputation: 6498
I am trying to create a handler for the exit signal in c and my operating system is ubuntu.
I am using sigaction method to register my custom handler method.
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
Here's my code
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
void CustomHandler(int signo)
{
printf("Inside custom handler");
switch(signo)
{
case SIGFPE:
printf("ERROR: Illegal arithmatic operation.\n");
break;
}
exit(signo);
}
void newCustomHandler(int signo)
{
printf("Inside new custom handler");
switch(signo)
{
case SIGINT:
printf("ERROR: Illegal arithmatic operation.\n");
break;
}
exit(signo);
}
int main(void)
{
long value;
int i;
struct sigaction act = {CustomHandler};
struct sigaction newact = {newCustomHandler};
newact = act;
sigaction(SIGINT, &newact, NULL); //whats the difference between this
/*sigaction(SIGINT, &act, NULL); // and this?
sigaction(SIGINT, NULL, &newact);*/
for(i = 0; i < 5; i++)
{
printf("Value: ");
scanf("%ld", &value);
printf("Result = %ld\n", 2520 / value);
}
}
Now when I run the program and press Ctrl + c it displays Inside Inside custom handler.
I have read the documentation for sigaction and it says
If act is non-null, the new action for signal signum is installed from act. If oldact is non-null, the previous action is saved in oldact.
why do I need to pass the second structure when I can directly assign the values like
newact = act
Thanks.
Upvotes: 2
Views: 3380
Reputation: 1
As Norman pointed out, you use oldact
because
you want the new handlers to be in effect for only a limited region of the code
But I think one thing previous answers fail to explain very clearly (at least I think it's the only thing needs to be explained here) is oldact
is what we read from sigaction.
As described in manual
If oldact is non-NULL, the previous action is saved in oldact.
Alternatively, you can keep track of previous act, but if you think that's too much trouble, you can extract sigaction in this way.
One scenario one might find this useful, is when there is a default handler for one signal, and you want to use your customized handler for the first (or first few) time(s), and then the signal (if you receive it for many times), would be processed by the default handler, since it takes a lot of trouble to find or rebuild default handler you can put this at the buttom of your handler.
struct sigaction default_sa;
void your_handler(int signum) {
//code for your handler
//...
sigaction(signum,&default_sa,NULL);//use default handler
return ;
}
int main(){
//replace SIGNUM with real signal number
sigaction(SIGNUM,NULL,&default_sa);
struct sigaction sa;
sa.sa_handler = your_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
sigaction(SIGNUM, &sa, NULL);
//your rest of main function code
//...
}
Upvotes: 0
Reputation: 12514
When you call sigaction
, you replace the old handler with the new one; the oldact
pointer is set to point to the handler information in effect before this replacement.
Perhaps, as is often the case, you want the new handlers to be in effect for only a limited region of the code: now that you know what the configuration was before you changed it, you can restore it by another call to sigaction
, at the end of this region.
Upvotes: 2
Reputation: 75629
oldact
is useful to reset the previous action handler:
sigaction(SIGINT, ©Interrupted, &previousHandler);
copy(something);
sigaction(SIGINT, &previousHandler, null);
This way, you can reset the previous signal handler even if you do not know what it was.
Upvotes: 6