pause() signal handler - c

The pause() function blocks until a signal arrives.
Assuming the process got a signal and pause() returned, does the signal handler will be executed before the code that follows the pause() call, or the result is unexpected?
Example:
void sigusr1_handler()
{
// .. handler code
}
void main()
{
// .. bind handler to SIGUSR1
pause(); // wait for SIGUSR1
// some more code
}
Does "some more code" will always be executed after sigusr1_handler() has finished, or there is a race condition? If so, what is the solution?
I cannot think of anything besides busy-waiting, but then the pause won't be needed at all..

Citing from the man page for pause(2):
pause() returns only when a signal was caught and the signal-catching function returned. In this case, pause() returns -1, and errno is set to EINTR.
You can be sure that your signal handler runs before some more code.

Signal handlers do not run concurrently; they interrupt the thread that handles them, and the interrupted flow only continues when the signal handler returns.
However, there may be other race conditions associated with your example; with just sparse pseudo-code and not a full explanation of your usage case, it's hard to say. For example a different signal might arrive and interrupt the pause before your signal does, and then your handler could end up running later than you expected.
There are several "right ways" to do this instead:
write a single byte to a pipe in the signal handler, and read from it in the main flow of execution.
sem_post a semaphore from the signal handler, and sem_wait in the main flow of execution.
Use sigwaitinfo or sigtimedwait instead of a signal handler.
Still use pause, but in a loop:
while(!signal_handler_finished) pause();
where signal_handler_finished has type volatile sig_atomic_t, and is set to a nonzero value in the signal handler.

Related

Stoping a process then using it again without killing it

Is there any way in C programming language , to stop a child process , and then call it again to start from the beginning? I have realised that if I use SIGKILL and then call the child process again nothing happens.
void handler {
printf(“entered handler”);
kill(getpid(),SIGKILL);
}
int main () {
pid_t child;
child=fork();
if (child<0) printf(“error”);
else if (child==0) {
signal(SIGINT,handler);
pause();
}
else {
kill(child,SIGINT);
kill(child,SIGINT);
}
This should print two times “Entered Handler” but it does not. Probably because it cannot call child again . Could I correct this in some way?
This should print two times “Entered Handler” but it does not.
Probably because it cannot call child again .
There are several problems here, but a general inability to deliver SIGINT twice to the same process is not one of them. The problems include:
The signal handler delivers a SIGKILL to the process in which it is running, effecting that process's immediate termination. Once terminated, the process will not respond to further signals, so there is no reason to expect that the child would ever print "entered handler" twice.
There is a race condition between the child installing a handler for SIGINT and the parent sending it that signal. If the child receives the signal before installing a handler for it, then the child will terminate without producing any output.
There is a race condition between the the first signal being accepted by the child and the second being delivered to it. Normal signals do not queue, so the second will be lost if delivered while the first is still pending.
There is a race condition between the child blocking in pause() and the parent signaling. If the signal handler were not killing the child, then it would be possible for the child to receive both signals before reaching the pause() call, and therefore fail to terminate at all.
In the event that the child made it to blocking in pause() before the parent first signaled it, and if it did not commit suicide by delivering itself a SIGKILL, then the signal should cause it to unblock and return from pause(), on a path to terminating normally. Thus, there would then also be a race condition between delivery of the second signal and normal termination of the child.
The printf() function is not async-signal safe. Calling it from a signal handler produces undefined behavior.
You should always use sigaction() to install signal handlers, not signal(), because the behavior of signal() is underspecified and varies in practice. The only safe use for signal() is to reset the disposition of a signal to its default.
Could I correct this in
some way?
Remove the kill() call from the signal handler.
Replace the printf() call in the signal handler with a corresponding write() call.
Use sigaction() instead of signal() to install the handler. The default flags should be appropriate for your use.
Solve the various race conditions by
Having the parent block SIGINT (via sigprocmask()) before forking, so that it will initially be blocked in the child.
Have the child use sigsuspend(), with an appropriate signal mask, instead of pause().
Have the child send some kind of response to the parent after returning from sigsuspend() (a signal of its own, perhaps, or a write to a pipe that the parent can read), and have parent await that response before sending the second signal.
Have the child call sigsuspend() a second time to receive the second signal.

Recursive signal call using kill function

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.
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().
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...

How to wait inside SIGABRT signal handler

I have a signal handler for SIGABRT , when the signal is received, i need some more time for other threads to exit gracefully. Then I will do _exit() inside signal handler to exit the entire process.
But I am not sure how to wait inside a signal handler. I think there are some limitations for using sleep inside signal handler. I dont want to use busy wait.
Somebody suggest any ideas please ?
There are no limitations of what kind of code you can execute inside a signal handler. You just have to keep in mind that another signal may arrive while executing your signal handler leaving you in the middle of half finished functions, locked mutexes or other things that should better remain uninterrupted.
Normally you would have the signal handler set a flag signalling to all threads to nicely exit, return from the signal handler and then have your code gracefully exit.

sem_wait interrupt signal on FreeBSD

I have noticed that on my copy of FreeBSD9 the man page for sem_wait from sempahore.h does not have a EINTR error return value. I currently have some code that has a signal handler, and I am raising a SIGINT signal. This does not seem to be waking up my sem_wait() so I can check the return value, thus the thread that is running the function wtih the sem_wait gets hung indefinitely.
According to the linux man page, I should be able to raise the singal, test for the EINTR value in the thread that is doing the sem_wait, but that seems to be missing in FreeBSD.
What is the right way of fixing this?
In psuedo here is what I have
signal_handler() //handles SIGINT
{
loopvar = 0;
}
thread 1:
while(loopvar)
{
if((r = sem_wait())
{
check error value
continue
}
..
sem_post()
}
thread 2:
raise(SIGINT);
so I was expecting when thread2 raises SIGINT it will cause sem_wait to return with a value, the loop would continue, but now loopvar would be zero, so I would exit my infinite loop.
edit: to be clear, I am not using the SA_RESTART flag.
raise raises the signal for the calling thread, not for the process. If you want to signal the whole process (with delivery to a random thread that has the signal unmasked), you need the kill function. If you want to signal a specific thread, you need pthread_kill.

Correct way to use signal handlers

What is the correct way to use signal handlers?
I saw the codes below from this question and was wondering why do you still need to put signal(SIGSEGV,sig_func); inside the sig_func? Wouldn't that create an unending loop when the process receives a SIGSEGV signal?
void sig_func(int sig)
{
write(1, "Caught signal 11\n", 17);
signal(SIGSEGV,sig_func);
}
int main()
{
signal(SIGSEGV,sig_func); //Install the signal handler
//Do work here
}
The signal manual says:
Finally, if the handler is set to a function sighandler then first either the handler is reset to SIG_DFL or an implementation-dependent blocking of the signal is performed and next sighandler is called with argument signum.
The repeat call to signal is used to reinstall the custom handler after it (might) have been reset to SIG_DFL.
in the example you provided, calling signal in sig_funct is useless because you have already set the signal handler in main and did not change it inside your handler.
considering your second question,no,it will not create an unending loop because signal() sets the disposition of the signal SIGSEGV to handler but do not execute it.

Resources