Sunday, October 12, 2014

Unix Prog: sigpending function

1. sigpending system definition

 ubuntu@ip-172-31-23-227:~$ less /usr/include/signal.h  
 ......  
 /* Put in SET all signals that are blocked and waiting to be delivered. */  
 extern int sigpending (sigset_t *__set) __THROW __nonnull ((1));  
 ......  

sigpending will return the set of currently pending signals

2. Example:
 #include<stdio.h>  
 #include<stdlib.h>  
 #include<unistd.h>  
 #include<signal.h>  
   
 void sig_quit(int signo)  
 {  
  printf("caught SIGQUIT\n");  
  if(signal(SIGQUIT, SIG_DFL) == SIG_ERR)  
   printf("can't reset SIGQUIT");  
 }  
   
 int main(int argc, char* argv[])  
 {  
  sigset_t newmask, oldmask, pendingmask;  
   
  // setup the sig_quit as signal handler for SIGQUIT  
  if(signal(SIGQUIT, sig_quit) == SIG_ERR) {  
   printf("signal error!\n");  
   exit(1);  
  }  
   
  // Block SIGQUIT and save current signal mask  
  sigemptyset(&newmask);  
  sigaddset(&newmask, SIGQUIT);  
  if(sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) {  
   printf("sigprocmask error!\n");  
   exit(1);  
  }  
   
  sleep(5); // during this period, user type ctrl / to send SIGQUIT  
   
  // Get the pending signals  
  if(sigpending(&pendingmask) < 0) {  
   printf("sigpending error!\n");  
   exit(2);  
  }  
  if(sigismember(&pendingmask, SIGQUIT)) {  
   printf("SIGQUIT pending\n");  
  }  
   
  // Reset the signal mask  
  // sigprocmask will make the pending signal delivered  
  if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) {  
   printf("sigprocmask error!\n");  
   exit(1);  
  }  
  printf("SIGQUIT unblocked!\n");  
   
  sleep(5); // during this period, user type ctrl / to send SIGQUIT  
  exit(0);  
 }  

shell:
The program firstly setup the SIGQUIT signal handler, and then fall into sleep for 5 seconds. During this period, user type Ctrl \ to send the SIGQUIT signal. After 5 seconds, the program call sigpending to get the pending signal, and SIGQUIT is in there.
Then the program calls sigprocmask to restore the old signal set, at this time, any pending signal will be delivered before the sigprocmask return, so sig_quit handler get executed, and reset the SIGQUIT signal to default action.
After unblocking the signal, the program fall into sleeping again, during this period, user type Ctrl \ again to send the SIGQUIT signal, which terminate the program.

For the second time, user typed 4 times of "Ctrl \", but only one SIGQUIT signal occurs, this indicates that the current system doesn't queue the pending signals.
 ubuntu@ip-172-31-23-227:~$ ./sigpending.out  
 ^\SIGQUIT pending  
 caught SIGQUIT  
 SIGQUIT unblocked!  
 ^\Quit (core dumped)  
 ubuntu@ip-172-31-23-227:~$ ./sigpending.out  
 ^\^\^\^\SIGQUIT pending  
 caught SIGQUIT  
 SIGQUIT unblocked!  
 ^\Quit (core dumped)  

No comments:

Post a Comment