sigsetjmp() and siglongjmp(): The mask signals are not the same on call to sigsetjmp() and return of siglongjmp()

According to man page:

If you want to portably save and restore signal masks, use sigsetjmp() and siglongjmp().

sigsetjmp() is similar to setjmp(). If, and only if, savesigs is nonzero, the process's current signal mask is saved in env and will be restored if a siglongjmp(3) is later performed with this env.

But in my program it is not true with above statements or I am missing something? The mask signals are not the same when sigsetjmp is called and when siglongjmp returns. I have written comments throughout the code to explain the question in detail. my question is why is it so?

Thanks in advanced

#include <setjmp.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

sigjmp_buf env;

static void handler(int signo)
      {
        printf("\ncatched signal: %d\n", signo);
        siglongjmp(env,1);
      }

int main(void)
   {
        struct sigaction action;

        action.sa_flags = 0;
        action.sa_handler = handler;

       if( (sigemptyset(&action.sa_mask) == -1) || (sigaction(SIGINT, &action, NULL) == -1) )
        {  
            perror("Failed to set!");
            return 1;
        }

       printf("this is process %ld\n", (long)getpid());

       //here I add the SIGSEGV to mask signals i.e action.sa_mask
       sigaddset(&action.sa_mask,SIGSEGV);
       sigaction(0, &action, NULL);
       sigaction(0, 0 , &action);
       printf("\nsigismember(&action.sa_mask, SIGSEGV)? 1 : 0 -> %d\n", sigismember(&action.sa_mask, SIGSEGV)? 1 : 0);
       //and yes it is member of mask signals i.e action.sa_mask

       if(sigsetjmp(env,1)) //"first time" it saves state of registers and mask signals and as return value is 0 it does not go inside
         {
            //when it comes here due to siglongjmp() the signal masks must be restored
            printf("Return to main loop due to ^c\n");

            //so again SIGSEGV must be member of mask signal i.e action.sa_mask as it was removed only after sigsetjmp was called
            sigaction(0 , 0 , &action);
            printf("sigismember(&action.sa_mask, SIGSEGV)? 1 : 0 -> %d\n", sigismember(&action.sa_mask, SIGSEGV)? 1 : 0);
            //but it shows it is NOT member of mask signal i.e action.sa_mask. why???
        }

    //here I delete the SIGSEGV from mask signals i.e action.sa_mask
    sigdelset(&action.sa_mask,SIGSEGV);
    sigaction(0, &action, NULL);
    sigaction(0, 0 , &action);

    printf("\nsigismember(&action.sa_mask, SIGSEGV)? 1 : 0 -> %d\n\n", sigismember(&action.sa_mask, SIGSEGV)? 1 : 0);

    for(;;);
}

output:

    majid@K53SC:~/Desktop$ ./a.out
    this is process 6335

    sigismember(&action.sa_mask, SIGSEGV)? 1 : 0 -> 1

    sigismember(&action.sa_mask, SIGSEGV)? 1 : 0 -> 0

    ^C
    catched signal: 2
    Return to main loop due to ^c
    sigismember(&action.sa_mask, SIGSEGV)? 1 : 0 -> 0

    sigismember(&action.sa_mask, SIGSEGV)? 1 : 0 -> 0

    ^C
    catched signal: 2
    Return to main loop due to ^c
    sigismember(&action.sa_mask, SIGSEGV)? 1 : 0 -> 0
    sigismember(&action.sa_mask, SIGSEGV)? 1 : 0 -> 0

Edit

I'm posting a correct program to show the concept of sigsetjmp() and siglongjmp() and how the signal mask is restored and it's output based on the answer Mr. Jean-Baptiste Yunès has given in the answer section so it may be helpful for others:

#include <setjmp.h>
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

sigjmp_buf env;

void handler(int signo)
    {
      printf("\nCaught signal: %s", strsignal(signo));
      siglongjmp(env,1);
    }

int main(void)
   {
      sigset_t pmask;

      if( (sigemptyset(&pmask) == -1) || (signal(SIGINT, handler)== SIG_ERR) )
        {  
           perror("Failed to set!");
           return 1;
        }

    sigprocmask(SIG_SETMASK, &pmask, NULL); //set the process signal mask to pmask

    sigprocmask(0, NULL, &pmask);           //check the process mask in pmask
    printf("\nsigismember(&pmask, SIGSEGV)? 1 : 0 -> %d", sigismember(&pmask, SIGSEGV)? 1 : 0);


    if(sigsetjmp(env,1)!=0)    //save process environment context and signal mask
        printf("\nReturn from signal handler to main loop\nProcess signal mask is restored by siglongjmp()!\n");

    else
        printf("\nProcess signal mask is saved by sigsetjmp()!\n");

    printf("\n**** This is process %ld ****", (long)getpid());
    sigprocmask(0, NULL, &pmask);           //ckeck the process mask to mask
    printf("\nsigismember(&pmask, SIGSEGV)? 1 : 0 -> %d", sigismember(&pmask, SIGSEGV)? 1 : 0);

    printf("\nChanging process signal mask");
    sigaddset(&pmask,SIGSEGV);
    sigprocmask(SIG_SETMASK, &pmask, NULL);

    sigprocmask(0, NULL, &pmask);           //ckeck the process mask to mask
    printf("\nsigismember(&pmask, SIGSEGV)? 1 : 0 -> %d\n\n", sigismember(&pmask, SIGSEGV)? 1 : 0);

    pause();
}

Output

majid@K53SC:~/Desktop$ gcc P45.c
majid@K53SC:~/Desktop$ ./a.out

sigismember(&pmask, SIGSEGV)? 1 : 0 -> 0
Process signal mask is saved by sigsetjmp()!

**** This is process 23099 ****
sigismember(&pmask, SIGSEGV)? 1 : 0 -> 0
Changing process signal mask
sigismember(&pmask, SIGSEGV)? 1 : 0 -> 1

^C
Caught signal: Interrupt
Return from signal handler to main loop
Process signal mask is restored by siglongjmp()!

**** This is process 23099 ****
sigismember(&pmask, SIGSEGV)? 1 : 0 -> 0
Changing process signal mask
sigismember(&pmask, SIGSEGV)? 1 : 0 -> 1

Answers


This is because you don't print the right information. You just print the action.sa_mask which is correct behavior, because you changed it by removing SIGSEGV from it.

What you want is to print the process mask available through sigprocmask, this is the value saved by sigsetjmp/siglongjmp.

-----EDIT----------------------------

From sigprocmask manual (GNU) :

The collection of signals that are currently blocked is called the signal mask. Each process has its own signal mask. When you create a new process (see Creating a Process), it inherits its parent’s mask. You can block or unblock signals with total flexibility by modifying the signal mask.

This mask is the one that is restored through siglongjmp calls.

From sigaction manual (GNU) about sa_mask field:

This specifies a set of signals to be blocked while the handler runs. Blocking is explained in Blocking for Handler. Note that the signal that was delivered is automatically blocked by default before its handler is started; this is true regardless of the value in sa_mask. If you want that signal not to be blocked within its handler, you must write code in the handler to unblock it.

So, using sigaction does not modify the process mask, but will modify it when an handler will be executed at some signal delivery.


Need Your Help

Bokeh : save plot but don't show it

python bokeh

I am using Bokeh to produce HTML code including figures with show method This method ends on opening default browser with HTML opened in it.

Which way should I create a list of objects when sending POST request

rest http-post django-rest-framework

When I creating same type objects and save them into database, should I send a list of that objects in one request or should I send individually for each one?