Thread: sigaction - how to find and invoke previous signal handler (sa_handler)

  1. #1
    Registered User
    Join Date
    Jul 2009
    Posts
    2

    sigaction - how to find and invoke previous signal handler (sa_handler)

    I have some shared libraries. I am doing sigaction in each and
    establishing a handler in each, but what I require is for whenever a
    handler in one of the shared libs gets a signal, it will do it's
    processing and then pass the signal on to the previous signal handler.
    E.g. main does sigaction, calls shlib1, which does sigaction; then main
    calls shlib2, which does sigaction. Eventually main gets a signal. What
    makes sense is that the handlers in shlib2, shlib1, then main should get
    control.

    How to do this.
    I tried the following (code is somewhat abbreviated):

    Code:
    void sighdlr( int sig )
    {
       struct sigaction oact, nex;
    
       sigaction( sig, NULL, &oact);
       if ( oact.sa_handler != SIG_DFL && oact.sa_handler != SIG_ERR && oact.sa_handler != SIG_IGN && oact.sa_handler != NULL ) {
          printf( "sighdlr: calling ohandler %p\n", oact.sa_handler );
         (oact.sa_handler)( sig );
       }
    }
    
    main()
    {
    struct sigaction sigact;
    memset( &sigact, 0, sizeof(sigact) );
    sigemptyset ( &sigact.sa_mask );   /* all signals unblocked */
    sigact.sa_handler   = hdlr;
    sigact.sa_flags = 0;
    sigaction( SIGTERM, &sigact,  NULL ); /* set up signal handler, don't
    care about the old handler - system should save it I think */
    
    shlib1();   /* sets up sigaction same as main does */
    shlib2()    /* ditto */
    pause();    /* wait for signal */
    }
    Now when I send kill -SIGTERM to the process, only the last sigaction
    isuer gets control (as I expect and want).
    The problem is that the sigaction( sig, NULL, &oact) gives the address of the LAST
    sigaction structure and thus the same sa_handler as the one currently running. NOT the
    one created by shlib1();
    I expect the queue of sigaction structures to be, in order: main, shlib1, shlib2; and if
    shlib2 gets a signal, the the previous should be the shlib1 sigaction structure etc.

    Seems the only way is to keep track of the sigaction structures myself in some, but
    that is a bit difficult if different folks are writing the shared libs.

    I Googled this for any examples, looked in Steven's book and cannot find no
    example of how to do this. Seems like a reasonable thing to try to
    handle, but it just does not work.

    Hopefully, this makes sense to someone and there is a way to obtain the list(in order) of the
    sigaction structures.

    Thanks,

    Jim

  2. #2
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    The "old handler" field contains the address of the most recently registered handler prior to the call to sigaction(). Since you are calling sigaction() within the signal handler itself, isn't it obvious that the previous call to sigaction() was the one which set up the current handler, and therefore the old handler is the same as the current handler?

    You need to cache the old handler the FIRST time you call sigaction(). Stuff it in a global variable. Done deal.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  3. #3
    Registered User
    Join Date
    Jul 2009
    Posts
    2

    sigaction - how to find and invoke previous signal handler (sa_handler)

    "isn't it obvious"

    Yes it was obvious after I ran it and saw the results.
    I realize that I could save the old.sa_handler or the oldact structure and use it.
    I was hoping that would not be necessary and that the kernel somehow kept a queue or list of the sigactions and I could get it from it rather than do all of the bookkeeping myself. Every single called shared lib has to keep track of all the previous signal handlers I guess.
    Thought there might be a better way.

    Thanks for the reply,

    Jim

  4. #4
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by j1mw3b View Post
    "isn't it obvious"

    Yes it was obvious after I ran it and saw the results.
    I realize that I could save the old.sa_handler or the oldact structure and use it.
    I was hoping that would not be necessary and that the kernel somehow kept a queue or list of the sigactions and I could get it from it rather than do all of the bookkeeping myself. Every single called shared lib has to keep track of all the previous signal handlers I guess.
    Thought there might be a better way.

    Thanks for the reply,

    Jim
    Registering a signal handler is a lot like hooking an interrupt or hooking an API call. It's pretty much cmomon practice that the installed hook should bounce control to the previous handler. If all the handlers do this, the effect is to distribute the signal/interrupt/API call down the chain of handlers. All you have to worry about is what YOUR library does. If some other library has installed a signal handler after you installed yours, and it does not contain code to call the old (your) signal handler, then that is that library's fault, not yours.

    It's not generally good design for a library to install a signal handler in the first place. Instead you should probably provide a function which the application can call when it receives the appropriate signal, and let the application handle the signal receiving on its own.

    It's just one of those things...
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

Popular pages Recent additions subscribe to a feed