1

Full program

Summery: Main process forks 3 child processes, sends a signal to each of these processes, and waits. In turn when each child receives signal it is redirected to child() function, sends a signal to main process (and calls to father() function), and then waits. If main process receives 3 signals it terminates child processes and ends the program.

The problem is that the main process receives a signal only once. I suspect that the other 2 signals are lost while the father() function is executed, or maybe I'm just missing something

Is there a way to know if some signals are lost? In that case how can I avoid this situation?

EatEmAll
  • 87
  • 11
  • What about setting a flag to look for x number of responses before terminating? You could also include a timeout delay in case one of the children gets hung up. – MLK.DEV Jan 03 '14 at 22:39
  • A flag would require the usage of a shared memory. Unfortunately I am required to implement this using signals only. – EatEmAll Jan 03 '14 at 22:44

2 Answers2

0

Signals are unreliable and should be avoided if you need to make sure that messages are being received. A more reliable way is to use

  1. pipe
  2. shared memory
  3. sockets
  4. file
Devolus
  • 21,661
  • 13
  • 66
  • 113
0

The use of pause() in the signal handler does not permit the signal to be delivered another time. Before the signal handler was entered, the signal was either masked or reset to its default action (most implementations do the former).

Another problem is that a signal from kill() may be coalesced with another instance of the same signal number. This happens if the receiving process does not get to run soon enough: if a new signal comes in when another is already pending for the same signal number, the new signal may be discarded. You can avoid this by using different signal numbers for each sender or by using sigqueue() and a handler installed with sigaction() with SA_SIGINFO set in sa_flags. Neither of these scale indefinitely.

It is wise to avoid use of the obsolete functions pause() and signal(). It is better to use sigsuspend() and sigaction() instead.

You can temporarily block signals using sigprocmask() or pthread_sigmask(). This will let you avoid race conditions such as signals coming in before the handler is installed.

The sigwait() function lets you handle signals in the main flow of the program.

Per convention, a normal termination is done with SIGTERM, not SIGQUIT. Note that the default action of SIGQUIT includes a core dump or similar.

jilles
  • 10,509
  • 2
  • 26
  • 39
  • I used `sigaction()` and `sigqueue()` like you suggested for SIGUSR1, but the main process still only gets 1 signal. [Here is a link to the updated code](https://gist.github.com/anonymous/7c7ab7dc3b8c0ae73247). I used an example from [here](http://stackoverflow.com/questions/3759467/how-do-i-receive-a-signal-sent-with-sigqueue-in-a-c-program-on-linux). Could you point to to what I did wrong? – EatEmAll Jan 04 '14 at 03:05
  • I also tried to use sigsuspend() instead of pause(). Didn't help. – EatEmAll Jan 04 '14 at 04:51
  • The use of `pause()` or `sigsuspend()` in the signal handler is wrong. Instead, the `pause()` in `main()` should be in a loop. – jilles Jan 04 '14 at 21:13