1

I'm now learning signals in computer system and I've stuck with a problem. There is a code given below;

int i = 0;
void handler(int s) {
  if(!i) kill(getpid(), SIGINT);
  i++;
}

int main() {
  signal(SIGINT, handler);
  kill(getpid(), SIGINT);
  printf("%d\n", i);
  return 0;
}

And the solution says that the possible output should be 0, 1, or 2. I understand that these are possible, but why not 3, 4 or others?

For example, we send SIGINT in the main function. Handler gets SIGINT signal, and send SIGINT as it is zero. Before it proceeds to the increment code, handler might be able to listen to SIGINT signal and send SIGINT signal one more time as it is executed before the increment code (i = 0) - loops again, again - and it might print out 3, 4, 5, or even bigger numbers.

2
  • 1
    Unless you have some external code that generates extra signals, there are only 2 signals generated for this process. Commented Jun 15, 2015 at 15:51
  • If you are learning signals, don't learn signal, instead learn sigaction. As the answers below suggest, the former does not have consistent semantics on all platforms. The latter does, and, importantly IMHO, forces you to specify just what kind of signal behavior you want. Commented Jun 15, 2015 at 17:57

2 Answers 2

2

Historically, lots of details about how signals work have changed. For instance, in the earliest variant, the processing of the signal reverted to default when the handler was called, and the handler had to re-establish itself. In this situation, sending the signal from the handler would kill the process.

Currently, it is often the case that while a handler is called for a particular signal, that signal is blocked. That means that the handler won't be called right then, but it will be called when the signal gets unblocked. Since there is no memory of how often the signal was sent, some of them may be "lost".

See POSIX <signal.h>, Signal Concepts, signal() and sigaction().

Sign up to request clarification or add additional context in comments.

Comments

1

This is because signals are usually blocked while delivered. So, in your example, the kill inside handler can't have effect at that place. You must wait to return from the handler to expect catching the signal again.

In theory, you can obtain 0 because it is unspecified when a signal is delivered. So, it is possible that you throw the signal in the main, and before its delivery you execute the printf.

You can get 1, because in general signal delivery occurs at the end of system call or begin or end of quantum. So in your case, just after sending the signal your return to user space and the signal is delivered, which produces the execution of the handler, incrementing i and then returning to the normal stream of execution and then prints.

You can have 2 because when returning from the handler, the signal is unblocked and then delivered for the second time. This is the more common case.

You can't have more than 2 because you set a condition for this. When i!=0 you don't throw the signal again, so it can't be thrown more than 2 times.

Beware that there is no "recursion" here...

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.