Searock
Searock

Reputation: 6498

What is the use of second structure(*oldact) in sigaction()

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

Answers (3)

hao ren
hao ren

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

Norman Gray
Norman Gray

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

Sjoerd
Sjoerd

Reputation: 75629

oldact is useful to reset the previous action handler:

sigaction(SIGINT, &copyInterrupted, &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

Related Questions