7

I am not new to the use of signals in programming. I mostly work in C/C++ and Python. But I am interested in knowing how signals are actually implemented in Linux (or Windows).

Does the OS check after each CPU instruction in a signal descriptor table if there are any registered signals left to process? Or is the process manager/scheduler responsible for this?

As signal are asynchronous, is it true that a CPU instruction interrupts before it complete?

Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208
  • 2
    Edited the post and removed various upper-case. Please refrain from using such outside source code, as it is often regarded as rude ("shouting") on the internet. – Lundin Oct 01 '12 at 11:54
  • Two articles are very helpful: [How signals are implemented in Linux](http://cs-pub.bu.edu/fac/richwest/cs591_w1/notes/wk3_pt2.PDF) and [The Linux Signals Handling Model](http://www.linuxjournal.com/article/3985) – Grijesh Chauhan Jan 23 '14 at 12:50

3 Answers3

8

The OS definitely does not process each and every instruction. No way. Too slow.

When the CPU encounters a problem (like division by 0, access to a restricted resource or a memory location that's not backed up by physical memory), it generates a special kind of interrupt, called an exception (not to be confused with C++/Java/etc high level language exception abstract).

The OS handles these exceptions. If it's so desired and if it's possible, it can reflect an exception back into the process from which it originated. The so-called Structured Exception Handling (SEH) in Windows is this kind of reflection. C signals should be implemented using the same mechanism.

Alexey Frunze
  • 61,140
  • 12
  • 83
  • 180
  • Thanks for answering!!.... I request you please read the http://cs-pub.bu.edu/fac/richwest/cs591_w1/notes/wk3_pt2.PDF. Some Interrupt Descriptor Table (IDT) described here also read slid number 18 says 'CPU checks for interrupts after executing each instruction'. is it really true?...all it bit unclear to me. – Grijesh Chauhan Oct 06 '12 at 12:04
  • 1
    The IDT is configured by the OS, but it's the CPU to fetch ISR addresses from it and transfer control there. And the CPU is the first to check for interrupts. Checking for interrupts in code is extremely inefficient. This job is best done by hardware, the CPU. If you are interested in how interrupts and exceptions work, please read the CPU manual (from Intel or AMD). It's all there, including the "delivery" of interrupts between instructions (yes, it's true). – Alexey Frunze Oct 06 '12 at 12:24
  • @Alexye Frunze: I posted a question here: http://stackoverflow.com/questions/12437648/uninterruptable-program-on-window-linux ... I request to you please have a look and suggest some hint. – Grijesh Chauhan Oct 12 '12 at 08:21
  • You've got pretty reasonable answers there. There isn't much to add. I wouldn't say it's impossible, but it's not easy to do that for obvious reasons: reliability + security. – Alexey Frunze Oct 12 '12 at 08:30
4

On the systems I'm familiar with (although I can't see why it should be much different elsewhere), signal delivery is done when the process returns from the kernel to user mode.

Let's consider the one cpu case first. There are three sources of signals:

  • the process sends a signal to itself
  • another process sends the signal
  • an interrupt handler (network, disk, usb, etc) causes a signal to be sent

In all those cases the target process is not running in userland, but in kernel mode. Either through a system call, or through a context switch (since the other process couldn't send a signal unless our target process isn't running), or through an interrupt handler. So signal delivery is a simple matter of checking if there are any signals to be delivered just before returning to userland from kernel mode.

In the multi cpu case if the target process is running on another cpu it's just a matter of sending an interrupt to the cpu it's running on. The interrupt does nothing other than force the other cpu to go into kernel mode and back so that signal processing can be done on the way back.

Art
  • 19,807
  • 1
  • 34
  • 60
2

A process can send signal to another process. process can register its own signal handler to handle the signal. SIGKILL and SIGSTOP are two signals which can not be captured.

When process executes signal handler, it blocks the same signal, That means, when signal handler is in execution, if another same signal arrives, it will not invoke the signal handler [ called blocking the signal], but it makes the note that the signal has arrived [ ie: pending signal]. once the already running signal handler is executed, then the pending signal is handled. If you do not want to run the pending signal, then you can IGNORE the signal.

The problem in the above concept is:

Assume the following: process A has registered signal handler for SIGUSR1.

  1) process A gets signal SIGUSR1, and executes signalhandler()
  2) process A gets SIGUSR1,
  3) process A gets SIGUSR1,
  4) process A gets SIGUSR1,

When step (2) occurs, is it made as 'pending signal'. Ie; it needs to be served. And when the step (3) occors, it is just ignored as, there is only one bit available to indicate the pending signal for each available signals.

To avoid such problem, ie: if we dont want to loose the signals, then we can use real time signals.

2) Signals are executed synchronously,

Eg.,

     1) process is executing in the middle of signal handler for SIGUSR1,

     2) Now, it gets another signal SIGUSR2, 

     3) It stops the SIGUSR1, and continues with SIGUSR2, 
        and once it is done with SIGUSR2, then it continues with SIGUSR1. 

3) IMHO, what i remember about checking if there are any signal has arrived to the process is:

1) When context switch happens.

Hope this helps to some extend.

Whoami
  • 13,930
  • 19
  • 84
  • 140