Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference in handling of Signals in UNIX

Tags:

c

unix

signals

Is there a difference between masking a signal using sigprocmask() and ignoring a signal using signal(<signal>, SIG_IGN)?

like image 865
shreyasva Avatar asked Apr 20 '11 13:04

shreyasva


People also ask

How are signals handled in UNIX?

A routine called by the UNIX system to process a signal is termed a signal handler. A software interrupt on an OpenVMS system is referred to as a signal, condition, or exception. A routine called by the OpenVMS system to process software interrupts is termed a signal handler, condition handler, or exception handler.

How signals are handled in Linux?

For a user, the most basic method is to press the INTERRUPT key or CONTROL-C when the script execute. When we enter Ctrl+C, the SIGINT signal is sent to the script, and, according to the defined default action, the script terminates. By using the kill command, we can also deliver the signals.


2 Answers

When you mask a signal it actually tells the kernel that this signal won't be delivered to the process till the mask is it.This doesn't means the signal wont occur ever again in the context of the process.Its just placed in a queue.This is usually done when you want to receive the signal but not during certain operation.A masked signal usually implies this signal can mean something to me but let it wait if it comes before I finish with this job. An ignored signal usually means that the signal is of no use to the process.

#include<stdio.h>
#include<signal.h>
#include<sys/types.h>
int main()
{
    sigset_t test; //test signal set

    alarm(1); //set alarm,SIGALRM generated after 1 second
    sigemptyset(&test);

    sigaddset(&test,SIGALRM);
    sigprocmask(SIG_SETMASK,&test,NULL); //mask sigalrm
    sleep(3); //sleep for 3 seconds ensuring the signal is generated and is         waiting in the queue
    sigprocmask(SIG_UNBLOCK,&test,NULL); //unblock
}

This refers to case 1.The signal is masked.But It lies there waiting and delivered as soon as you need it The strace output confirms this

   alarm(1)                                = 0
   rt_sigprocmask(SIG_SETMASK, [ALRM], NULL, 8) = 0
   rt_sigprocmask(SIG_BLOCK, [CHLD], [ALRM], 8) = 0
   rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
   rt_sigprocmask(SIG_SETMASK, [ALRM], NULL, 8) = 0
   nanosleep({3, 0}, 0xbfee9ea4)           = 0
   rt_sigprocmask(SIG_UNBLOCK, [ALRM], NULL, 8) = 0
   --- SIGALRM (Alarm clock) @ 0 (0) ---
   +++ killed by SIGALRM +++

While for the second case

 #include<stdio.h>
 #include<signal.h>
 int main()
{
    alarm(1);
    signal(SIGALRM,SIG_IGN);

    sleep(3);
    signal(SIGALRM,SIG_DFL);
    return 0;
}

The strace o/p suggest a different story

   alarm(1)                                = 0
   rt_sigaction(SIGALRM, {SIG_IGN, [ALRM], SA_RESTART}, {SIG_DFL, [], 0}, 8) = 0
   rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
   rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
   rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
   nanosleep({3, 0}, {2, 691998})          = ? ERESTART_RESTARTBLOCK (To be restarted)
   --- SIGALRM (Alarm clock) @ 0 (0) ---
   restart_syscall(<... resuming interrupted call ...>) = 0
   rt_sigaction(SIGALRM, {SIG_DFL, [ALRM], SA_RESTART}, {SIG_IGN, [ALRM], SA_RESTART},                         8) = 0
   exit_group(0)                           = ?

The signal did got delivered but nothing happened except interrupting(and restarting sleep).

like image 20
bashrc Avatar answered Sep 28 '22 05:09

bashrc


Blocking is different from ignoring. You ignore a signal by installing SIG_IGN with sigaction().

After a signal is generated by the kernel or a process, the kernel makes it pending to some process(es). The signal is said to be delivered to a process once the process acts on the signal. A process may block a signal, which leaves the signal pending until it is unblocked. A signal which is not blocked will be delivered immediately. The signal mask specifies which signals are blocked. A process can determine which signals are pending.

Most UNIX's will not queue multiple instances of the same pending signal; only one instance of each signal can be pending.

Setting a signal action to SIG_IGN for a signal that is pending will cause the pending signal to be discarded, whether or not it is blocked.

And the process signal mask contains the set of signals that are currently blocked.

When a process blocks a signal, an occurrence of the signal is held until the signal is unblocked (blocked signals do not get lost, whereas ignored signals do get lost).

like image 99
Lars Avatar answered Sep 28 '22 06:09

Lars