sem_wait interrupt signal on FreeBSD - c

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.

Related

Signal can't wake up sleeping process

I'm working on a project which requires to take care of process scheduling. I tried to stop certain process by sending SIGINT signal(ctrl+c), but i found out sleeping process doesn't wake up.
I solved this weird issue but couldn't find out why SIGINT signal couldn't wake up sleeping process.
Here's my original code (where process is stuck) :
set_current_state(TASK_INTERRUPTIBLE);
while (!item->assigned) {
schedule_timeout(2*HZ);
set_current_state(TASK_INTERRUPTIBLE);
}
set_current_state(TASK_RUNNING);
So inside of the while loop, when !item->assigned is still 1, SIGINT signal doesn't do anything even though process' state is set to TASK_INTERRUPTIBLE.
As far as I know, process takes care of signal in these ways:
execute the signal default action
block the signal setting a signal mask (this is done using the system call sigmask)
assign a custom handler to the signal, executing a custom action (using the system call signal)
So in this case I assumed It would execute the default action..
I added signal_pending(current) to check if there is any pending signal, and if it is, then break out of the loop so that the process can handle the pending signal.
set_current_state(TASK_INTERRUPTIBLE);
while (!item->assigned) {
schedule_timeout(2*HZ);
if (signal_pending(current))
{
break;
}
set_current_state(TASK_INTERRUPTIBLE);
}
set_current_state(TASK_RUNNING);
But still no idea why It didn't catch the SIGINT signal.

Raising SIGINT, but getting stuck in thread in c

I'm doing a program that utilizes threads. I also have a SIGINT handler that closes everything correctly, for an orderly shutdown. However, since my threads are in a while(1) loop the pthread_join function in my handler gets stuck and i have to press ctrl+c a bunch of times, to close each thread singularly. How can i do this with just 1 click?
Here's my thread worker function:
void *worker(){
struct message msg;
while(1){
if(wr.fnode != NULL){
sem_wait(&tsem);
stats->nptri++;
msg.patient = *(wr.fnode);
wr_deletefnode();
sem_post(&tsem);
sleep((float)(msg.patient.ttime/1000));
msgsnd(mqid,&msg,sizeof(msg)-sizeof(long),0);
}
}
}
It's depend how you are sending signal (SIGINT or any) to a thread. for sending a signal to thread you should use pthread_kill() instead of kill() or raise() because signal handler(signal or sigaction) handles only processes ,not threads.
int pthread_kill(pthread_t thread, int sig);
If you ever try to kill running thread using kill command/function OS will throw warning like Warning: Program '/bin/bash' crashed.
observe running thread using ps -eL | grep pts/0 before and after sending signal.
I hope you got something.
Two things you need to solve:
How to break the endless while loop
How to return from blocking system call (like for example sem_wait())
Referring 1.:
Change
while (1)
to be
while (!exit_flag)
Define exit_flag globally
volatile sig_atomic_t exit_flag = 0;
and set it to 1 on reception of the SIGINT signal.
To catch a signal do not setup a signal handler, but create a separate thread using sigwait() to wait for and receive a SIGINT.
Make sure all other threads are created blocking SIGINT.
Referring 2.:
Keep track of all thread running by memorising their thread-ids.
After the signal-listener thread mentioned under 1. set the exit_flag, then loop over the list of running threads and one by one
enable them to receive SIGINT
signal them using pthread_kill(), in case they were stuck inside a system call, the call would return setting errno to EINTR.
join the thread calling pthread_join().

pause() signal handler

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.

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

Persistent signal handling

I'm trying to write a signal handler to catch any number of consecutive SIGINT signals and prevent the program from exiting. The program is a simple file server. The handler sets a global flag which causes the while loop accepting new connections to end, a call to pthread_exit() ensures that main lets current connections finish before exiting. It all goes like clockwork when I hit ctrl-C once but a second time exits the program immediately.
I tried first with signal():
signal(SIGINT, catch_sigint);
...
static void catch_sigint(int signo)
{
...
signal(SIGINT, catch_sigint);
}
I also tried it using sigaction:
struct sigaction sigint_handler;
sigint_handler.sa_handler = catch_sigint;
sigemptyset(&sigint_handler.sa_mask);
sigint_handler.sa_flags = 0;
sigaction(SIGINT, &sigint_handler, NULL);
Unsure how to "reinstall" this one I just duplicated this code in the handler similar to the handler using the signal() method.
Neither one of these works as I expected.
Additional info:
The program is a simple file server. It receives a request from the client which is simply a string consisting of the requested file name. It utilizes pthreads so that transfers can occur simultaneously. Upon receiving SIGINT I wish for the server to exit the while loop and wait for all current transfers to complete then close. As is, no matter how I code the signal handler a second SIGINT terminates the program immediately.
int serverStop = 0;
...
int main()
{
/* set up the server -- socket(), bind() etc. */
struct sigaction sigint_hadler;
sigint_handler.sa_handler = catch_sigint;
sigint_handler.sa_flags = 0;
sigemptyset(&sigint_handler.sa_mask);
sigaction(SIGINT, &sigint_handler, NULL);
/* signal(SIGINT, catch_sigint); */
while(serverStop == 0)
{
/* accept new connections and pthread_create() for each */
}
pthread_exit(NULL);
}
...
static void catch_sigint(int signo)
{
serverStop = 1;
/* signal(SIGINT, catch_sigint) */
}
I don't think any other code could be pertinent but feel free to ask for elaboration
On Linux, you should not have to reinstall the signal handler, using either signal (which implements BSD semantics by default) or sigaction.
when I hit ctrl-C once but a second time exits the program immediately.
That's not because your handler got reset, but likely because your signal handler is doing something it shouldn't.
Here is how I would debug this issue: run the program under GDB and
(gdb) catch syscall exit
(gdb) catch syscall exit_group
(gdb) run
Now wait a bit for the program to start working, and hit Control-C. That will give you (gdb) prompt. Now continue the program as if it has received SIGINT: signal SIGINT (this will invoke your handler). Repeat the 'Control-C/signal SIGINT' sequence again. If you get stopped in either exit or exit_group system call, see where that is coming from (using GDB where command).
Update:
Given the new code you posted, it's not clear exactly where you call pthread_exit to "ensures that main lets current connections finish before exiting". As written, your main thread will exit the loop on first Control-C, and proceed to call exit which would not wait for other threads to finish.
Either you didn't show your actual code, or the "second Control-C" is a red herring and your first Control-C takes you out already (without finishing work in other threads).
NOTE: this is largely guesswork.
I'm pretty sure that calling pthread_exit in the main thread is a bad idea. If the main thread has quit, then the OS may try to send subsequent signals to some other thread.
I recommend that instead of using pthread_exit in the main thread, you just pthread_join() all the other threads, then exit normally.
But it's also important to ensure that the other threads do not get the signals. Normally this is done with sigprocmask (or maybe more correctly pthread_sigmask, which is the same under Linux) to mask the signal out in the worker threads. This ensures that the signal is never delivered to them.
Note that to avoid race conditions, you should use pthread_sigmask in the main thread just before creating a child thread, then set the signal mask back again in the main thread afterwards. This ensures that there is no window, however small, during which a child thread can possibly get unwanted signals.
I'm not sure to understand. A signal handler should usually not re-install any signal handler (including itself), because the signal handler stays in function till another is installed. See also SA_NODEFER flag to sigaction to be able to catch the signal during its handling.
A signal handler should be short. See my answer to this question. It usually mostly sets a volatile sig_atomic_t variable.
What is not working? Don't do complex or long-lasting processing inside signal handlers.
Please show your code...

Resources