Sometimes we may want that flow of execution of a critical/time-critical portion of the program should not be hampered by the occurrence of one or more signals. In such a case we may decide to block the signal. Once we are through with the critical/time-critical code we can unblock the signals(s). Note that if a signal arrives when it is blocked it is simply queued into a signal queue. When the signals are unblocked the process immediately receives all the pending signals one after another. Thus blocking of signals defers the delivery of signals to a process till the execution of some critical/time-critical code is over. Instead of completely ignoring the signals or letting the signals interrupt the execution, it is preferable to block the signals for the moment and deliver them some time later. Let us now write a program to understand signal blocking. Here is the program…
# include <unistd.h>
# include <sys/types.h>
# include <signal.h>
# include <stdio.h>
void sighandler ( int signum )
{
switch ( signum )
{
case SIGTERM :
printf ( "SIGTERM Received\n" ) ;
break ;
case SIGINT :
printf ( "SIGINT Received\n" ) ;
break ;
case SIGCONT :
printf ( "SIGCONT Received\n" ) ;
break ;
}
}
int main( )
{
char buffer [ 80 ] = "\0” ;
sigset_t block ;
signal ( SIGTERM, sighandler ) ;
signal ( SIGINT, sighandler ) ;
signal ( SIGCONT, sighandler ) ;
sigemptyset ( &block ) ;
sigaddset ( &block, SIGTERM ) ;
sigaddset ( &block, SIGINT ) ;
sigprocmask ( SIG_BLOCK, &block, NULL ) ;
while ( strcmp ( buffer,"n" ) != 0 )
{
printf ( "Enter a String: " ) ;
gets ( buffer ) ;
puts ( buffer ) ;
}
sigprocmask ( SIG_UNBLOCK, &block, NULL ) ;
while ( 1 )
printf ( "\rProgram Running" ) ;
return 0 ;
}
printf ( "SIGCONT Received\n" ) ;
break ;
}
}
int main( )
{
char buffer [ 80 ] = "\0” ;
sigset_t block ;
signal ( SIGTERM, sighandler ) ;
signal ( SIGINT, sighandler ) ;
signal ( SIGCONT, sighandler ) ;
sigemptyset ( &block ) ;
sigaddset ( &block, SIGTERM ) ;
sigaddset ( &block, SIGINT ) ;
sigprocmask ( SIG_BLOCK, &block, NULL ) ;
while ( strcmp ( buffer,"n" ) != 0 )
{
printf ( "Enter a String: " ) ;
gets ( buffer ) ;
puts ( buffer ) ;
}
sigprocmask ( SIG_UNBLOCK, &block, NULL ) ;
while ( 1 )
printf ( "\rProgram Running" ) ;
return 0 ;
}
In this program we have registered a common handler for the SIGINT, SIGTERM and SIGCONT signals. Next we want to repeatedly accept strings in a buffer and display them on the screen till the time the user does not enter an ‘n’ from the keyboard. Additionally, we want that this activity of receiving input should not be interrupted by the SIGINT or the SIGTERM signals. However, a SIGCONT should be permitted. So before we proceed with the loop we must block the SIGINT and SIGTERM signals. Once we are through with the loop we must unblock these signals. This blocking and unblocking of signals can be achieved using the sigprocmask( ) library function.
The first parameter of the sigprocmask( ) function specifies whether we want to block/unblock a set of signals. The next parameter is the address of a structure (typedefed as sigset_t) that describes a set of signals that we want to block/unblock. The last parameter can be either NULL or the address of sigset_t type variable which would be set up with the existing set of signals before blocking/unblocking signals.
There are library functions that help us to populate the sigset_t structure. The sigemptyset( ) empties a sigset_t variable so that it does not refer to any signals. The only parameter that this function accepts is the address of the sigset_t variable. We have used this function to quickly initialize the sigset_t variable block to a known empty state. To block the SIGINT and SIGTERM we have to add the signals to the empty set of signals. This can be achieved using the sigaddset( ) library function. The first parameter of sigaddset( ) is the address of the sigset_t variable and the second parameter is the ID of the signal that we wish to add to the existing set of signals.
After the loop we have also used an infinite while loop to print the ‘Program running’ message. This is done so that we can easily check that till the time the loop that receives input is not over the program cannot be terminated using Ctrl + C or kill command since the signals are blocked. Once the user enters ‘n’ from the keyboard the execution comes out of the while loop and unblocks
the signals. As a result, pending signals, if any, are immediately delivered to the program. So if we press Ctrl + C or use the kill command when the execution of the loop that receives input is not over these signals would be kept pending. Once we are through with the loop the signal handlers would be called.
No comments:
Post a Comment