Will signals be delivered to a program blocked on POSIX semaphore? - c

This really is two questions, but I suppose it's better they be combined.
We're working on a client that uses asynchronous TCP connection. The idea is that the program will block until certain message is received from the server, which will invoke a SIGPOLL handler. We are using a busy waiting loop, basically:
var = 1
while (var) usleep(100);
//...and somewhere else
void sigpoll_handler(int signum){
......
var = 0;
......
}
We would like to use something more reliable instead, like a semaphore. The thing is, when a thread is blocked on a semaphore, will the signal get through still? Especially considering that signals get delivered when it switches back to user level; if the process is off the runqueue, how will it happen?
Side question (just out of curiosity):
Without the "usleep(100)" the program never progresses past the while loop, although I can verify the variable was set in the handler. Why is that? Printing changes its behaviour too.
Cheers!

[too long for a comment]
Accessing var from inside the signal handler invokes undefined behaviour (at least for a POSIX conforming system).
From the related POSIX specification:
[...] if the process is single-threaded and a signal handler is executed [...] the behavior is undefined if the signal handler refers to any object [...] with static storage duration other than by assigning a value to an object declared as volatile sig_atomic_t [...]
So var shall be defined:
volatile sig_atomic_t var;
The busy waiting while-loop, can be replaced by a single call to a blocking pause(), as it will return on reception of the signal.
From the related POSIX specification:
The pause() function shall suspend the calling thread until delivery of a signal whose action is either to execute a signal-catching function or to terminate the process.
Using pause(), btw, will make the use of any global flag like var redundant, to not say needless.

Short answer: yes, the signal will get through fine with a good implementation.
If you're going to be using a semaphore to control the flow of the program, you'll want to have the listening be on one child with the actual data processing be on another. This will then put the concurrency fairness in the hands of the OS which will make sure your signal listening thread gets a chance to check for a signal with some regularity. It shouldn't ever be really "off the runqueue," but cycling through positions on the runqueue instead.
If it helps you to think about it, what you have right now seems to basically be a a very rough implementation of a semaphore on its own -- a shared variable whose value will stop one block of code from executing until another code block clears it. There isn't anything inherently paralyzing about a semaphore on a system level.
I kind of wonder why whatever function you're using to listen for the SIGPOLL isn't doing its own blocking, though. Most of those utilities that I've seen will stop their calling thread until they return a value. Basically they handle the concurrency for you and you can code as if you were dealing with a normal synchronous program.
With regards to the usleep loop: I'd have to look at what the optimizer's doing, but I think there are basically two possibilities. I think it's unlikely, but it could be that the no-body loop is compiling into something that isn't actually checking for a value change and is instead just looping. More likely to me would be that the lack of any body steps is messing up the underlying concurrency handling, and the loop is executing so quickly that nothing else is getting a chance to run -- the queue is being flooded by loop iterations and your signal processsing can't get a word in edgewise. You could try just watching it for a few hours to see if anything changes; theoretically if it's just a concurrency problem then the random factor involved could clear the block on its own with a few billion chances.

Related

Cancelling calculation early using pthreads

I have a program in c where I want to do some calculations which may or may not take a very long time. It is hard to know beforehand how much time the calculations will take. The program has a cli so right now I usually do something like this
./program
do calculation 243
and it starts calculating. If I want to cancel it because it takes to much time I do ctrl+c and restart the program with another calculation. Now I would like for the program to cancel the calculation itself after either q has been pressed or for example 10 seconds has passed.
I have found a way which seems to do what I expect using pthreads. I'm however wondering if this is recommended or if there are for example any memory leaks or other things that can happen.
The following is my code
void *pthread_getc(void *ptr) {
char c = '\0';
while (c != 'q')
c = getc(stdin);
pthread_cancel((pthread_t)ptr);
}
void *pthread_sleep(void *ptr) {
sleep(10);
pthread_cancel((pthread_t)ptr);
}
void pthread_cancellable(void *(*ptr)(void *), struct arg *arg) {
pthread_t thread_main, thread_getc, thread_sleep;
pthread_create(&thread_main, NULL, ptr, (void *)arg);
pthread_create(&thread_getc, NULL, pthread_getc, (void *)thread_main);
pthread_create(&thread_sleep, NULL, pthread_sleep, (void *)thread_main);
pthread_join(thread_main, NULL);
pthread_cancel(thread_getc);
pthread_cancel(thread_sleep);
pthread_join(thread_getc, NULL);
pthread_join(thread_sleep, NULL);
}
the idea being that both pthread_getc and pthread_sleep can cancel main, and once main is cancelled so are these two. Then I simply call pthread_cancellable where the first argument is a function doing the calculation and the second argument is the arguments to the calculating function.
Can something go wrong with memory leaks here or something else? Is there an easier/better way to this in c?
What happens if main is cancelled two times and if a thread gets cancelled when its already done?
Can something go wrong with memory leaks here or something else?
If the program is going to terminate after aborting the computation then there is no issue with memory leaks. The system does not rely on processes to clean up after themselves -- it will reclaim all memory allotted to the process no matter how the process used it.
But your code violates the #1 rule of pthread_cancel(): never call pthread_cancel(). And although monitoring stdin for a q keystroke could work, that's a bit odd, and it potentially gets in the way of using stdin for something else you want to add to your program later.
Is there an easier/better way to this in c?
Yes. In the first place, if the objective is simply to terminate the program at timeout / user interrupt, then do that. That is is, have any thread call exit() when you want to terminate. You do not need to cancel any threads for that.
In the second place, I don't see what is gained by implementing a custom keyboard action (type 'q' to abort) when the standard interrupt signal sent by Ctrl-C works fine, and you even get the latter for free. If you want or need to perform some kind of extra behavior in response to an interrupt signal (before or instead of terminating), then register a handler for it.
There are multiple ways you could implement the early termination behavior, but here are outlines of two I like:
No-frills abortion upon timeout (or Ctrl-C):
Only the program's initial thread is needed.
Before it launches the computation, it creates and starts an interval timer (timer_create()) to count down the timeout. Configure the timer to raise SIGINT when it expires.
That's it. You get termination via the keyboard (albeit with Ctrl-C as you already do, not 'q') and the same termination behavior as far as an external observer can see in the event of a timeout.
optional addition 1:
If desired, you can install a handler for SIGINT to get extra or different behavior upon cancellation than you otherwise would. Note, however, that there are significant limits on what a signal handler may do. For example, maybe you want to emit a message to stderr (use write(), not fprintf() for such things), or you want to exit() with non-zero status instead of terminating (directly) because of the signal.
optional addition 2:
If the program reaches a point where it is not finished but it no longer wants to be terminated when the timeout is reached then it may at that point use timer_delete() to disable the timer.
With-frills abortion upon timeout (or Ctrl-C):
If you want to perform work in response to abort of the computation that is unsuited for a signal handler (too much, needs to call functions that are not async-signal-safe, ...) then you need a thread to do that in, and additional control structures and mechanisms. This is one way to do it:
Create and initialize a mutex, a condition variable, and a flag of type sig_atomic_t, all at file scope. The contract for these is that the flag may be accessed (read or write) only by a thread that currently holds the mutex locked, and that the mutex is the same that will be associated with all waits on the CV.
Install a signal handler for SIGINT that
locks the mutex
Provided that the flag does not indicate completion, updates it to indicate cancellation
unlocks the mutex
broadcasts to the CV
The last thing the computational thread will do after completing its work is (with the mutex locked) set the flag to a value indicating completion, and then broadcast to the CV.
The initial thread will then do this:
Setup as described in the previous points
lock the mutex
Create / start an interval timer (timer_create()) that raises SIGINT when it expires, after the chosen timeout period.
Start the computational thread
loop while the flag indicates ongoing computation. In the loop body
perform a wait on the CV
The computation having either completed successfully or been canceled at this point, perform whatever final actions are appropriate and then terminate, either by returning from main() or by calling exit().
That's still pretty clean, gets you both timeout-based and keyboard-based cancellation (albeit the latter with Ctrl-C instead of 'q'), puts all the cancellation handling in one place, and requires only one thread in addition to the computational one.
optional addition: abort in response to 'q'
Although I do not recommend it, if you really must have that termination by typing 'q', then you can set up another thread that monitors for that keypress / character, and performs a raise(SIGINT) if it sees it.

Race conditions can also occur in traditional, single-threaded programs - Clarity

I have read few books on parallel programming over the past few months and I decided to close it off with learning about the posix thread.
I am reading "PThreads programming - A Posix standard for better multiprocessing nutshell-handbook". In chapter 5 ( Pthreads and Unix ) the author talks about handling signals in multi-threaded programs. In the "Threadsafe Library Functions and System Calls" section, the author made a statement that I have not seen in most books that I have read on parallel programming. The statement was:
Race conditions can also occur in traditional, single-threaded programs that use signal handlers or that call routines recursively. A single-threaded program of this kind may have the same routine in progress in various call frames on its process stack.
I find it a little bit tedious to decipher this statement. Does the race condition in the recursive function occur when the recursive function keeps an internal structure by using the static storage type?
I would also love to know how signal handlers can cause RACE CONDITION IN SINGLE THREADED PROGRAMS
Note: Am not a computer science student , i would really appreciate simplified terms
I don't think one can call it a race condition in the classical meaning. Race conditions have a somewhat stochastic behavior, depending on the scheduler policy and timings.
The author is probably talking about bugs that can arise when the same object/resource is accessed from multiple recursive calls. But this behavior is completely deterministic and manageable.
Signals on the other hand is a different story as they occur asynchronously and can apparently interrupt some data processing in the middle and trigger some other processing on that data, corrupting it when returned to the interrupted task.
A signal handler can be called at any time without warning, and it potentially can access any global state in the program.
So, suppose your program has some global flag, that the signal handler sets in response to,... I don't know,... SIGINT. And your program checks the flag before each call to f(x).
if (! flag) {
f(x);
}
That's a data race. There is no guarantee that f(x) will not be called after the signal happens because the signal could sneak in at any time, including right after the "main" program tests the flag.
First it is important to understand what a race condition is. The definition given by Wikipedia is:
Race conditions arise in software when an application depends on the sequence or timing of processes or threads for it to operate properly.
The important thing to note is that a program can behave both properly and improperly based on timing or ordering of execution.
We can fairly easily create "dummy" race conditions in single threaded programs under this definition.
bool isnow(time_t then) {
time_t now = time(0);
return now == then;
}
The above function is a very dumb example and while mostly it will not work, sometimes it will give the correct answer. The correct vs. incorrect behavior depends entirely on timing and so represents a race condition on a single thread.
Taking it a step further we can write another dummy program.
bool printHello() {
sleep(10);
printf("Hello\n");
}
The expected behavior of the above program is to print "Hello" after waiting 10 seconds.
If we send a SIGINT signal 11 seconds after calling our function, everything behaves as expected. If we send a SIGINT signal 3 seconds after calling our function, the program behaves improperly and does not print "Hello".
The only difference between the correct and incorrect behavior was the timing of the SIGINT signal. Thus, a race condition was introduced by signal handling.
I'm going to give a more general answer than you asked for. And this is my own, personal, pragmatic answer, not necessarily one that hews to any official, formal definition of the term "race condition".
Me, I hate race conditions. They lead to huge classes of nasty bugs that are hard to think about, hard to find, and sometimes hard to fix. So I don't like doing programming that's susceptible to race conditions. So I don't do much classically multithreaded programming.
But even though I don't do much multithreaded programming, I'm still confronted by certain classes of what feel to me like race conditions from time to time. Here are the three I try to keep in mind:
The one you mentioned: signal handlers. Receipt of a signal, and calling of a signal handler, is a truly asynchronous event. If you have a data structure of some kind, and you're in the middle of modifying it when a signal occurs, and if your signal handler also tries to modify that same data structure, you've got a race condition. If the code that was interrupted was in the middle of doing something that left the data structure in an inconsistent state, the code in the signal handler might be confused. Note, too, that it's not necessarily code right in the signal handler, but any function called by the signal handler, or called by a function that's called by the signal handler, etc.
Shared OS resources, typically in the filesystem: If your program accesses (or modifies) a file or directory in the filesystem that's also being accessed or modified by another process, you've got a big potential for race conditions. (This is not surprising, because in a computer science sense, multiple processes are multiple threads. They may have separate address spaces meaning they can't interfere with each other that way, but obviously the filesystem is a shared resource where they still can interfere with each other.)
Non-reentrant functions like strtok. If a function maintains internal, static state, you can't have a second call to that function if another instance is active. This is not a "race condition" in the formal sense at all, but it has many of the same symptoms, and also some of the same fixes: don't use static data; do try to write your functions so that they're reentrant.
The author of the book in which you found seems to be defining the term "race condition" in an unusual manner, or maybe he's just used the wrong term.
By the usual definition, no, recursion does not create race conditions in single-threaded programs because the term is defined with respect to the respective actions of multiple threads of execution. It is possible, however, for a recursion to produce exposure to non-reentrancy of some of the functions involved. It's also possible for a single thread to deadlock against itself. These do not reflect race conditions, but perhaps one or both of them is what the author meant.
Alternatively, maybe what you read is the result of a bad editing job. The text you quoted groups functions that employ signal handling together with recursive functions, and signal handlers indeed can produce data races, just as a multiple threads can do, because execution of a signal handler has the relevant characteristics of execution of a separate thread.
Race conditions absolutely happen in single-threaded programs once you have signal handlers. Look at the Unix manual page for pselect().
One way it happens is like this: You have a signal handler that sets some global flag. You check your global flag and because it is clear you make a system call that suspends, confident that when the signal arrives the system call will exit early. But the signal arrives just after you check the global flag and just before the system call takes place. So now you're hung in a system call waiting for a signal that has already arrived. In this case, the race is between your single-threaded code and an external signal.
Well, consider the following code:
#include <pthread.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int num = 2;
void lock_and_call_again() {
pthread_mutex_lock(&mutex);
if(num > 0) {
--num;
lock_and_call_again();
}
}
int main(int argc, char** argv) {
lock_and_call_again();
}
(Compile with gcc -pthread thread-test.c if you safe the code as thread-test.c)
This is clearly single-threaded, isn't it?
Never the less, it will enter a dead-lock, because you try to lock an already locked mutex.
That's basically what is meant within the paragraph you cited, IMHO:
It does not matter whether it is done in several threads or one single thread, if you try to lock an already locked mutex, your program will end in an dead-lock.
If a function calls itself, like lock_and_call above, it what is called a recursive call .
Just as james large explains, a signal can occur any time, and if a signal handler is registered with this signal, it will called at unpredictable times, if no measures are taken, even while the same handler is already being executed - yielding some kind of implicit recursive execution of the signal handler.
If this handler aquires some kind of a lock, you end up in a dead-lock, even without a function calling itself explicitly.
Consider the following function:
pthread_mutex_t mutex;
void my_handler(int s) {
pthread_mutex_lock(&mutex);
sleep(10);
pthread_mutex_unnlock(&mutex);
}
Now if you register this function for a particular signal, it will be called whenever the signal is caught by your program. If the handler has been called and sleeps, it might get interrupted, the handler called again, and the handler try to lock the mutex that is already locked.
Regarding the wording of the citation:
"A single-threaded program of this kind may have the same routine in progress in various call frames on its process stack."
When a function gets called, some information is stored on the process's stack - e.g. the return address. This information is called a call frame. If you call a function recursively, like in the example above, this information gets stored on the stack several times - several call frames are stored.
It's stated a littlebit clumsy, I admit...

Is pthread_kill() dangerous to use?

I have read that TerminateThread() in WinAPI is dangerous to use.
Is pthread_kill() in Linux also dangerous to use?
Edit: Sorry I meant pthread_kill() and not pthread_exit().
To quote Sir Humphrey Appleby, the answer is "yes, and no".
In and of itself calling pthread_exit() is not dangerous and is called implicitly when your thread exits its method. However, there are a few "gotchas" if you call it manually.
All cleanup handlers are called when this is called. So if you call this method, then access some memory that the cleanup handlers have cleaned up, you get a memory error.
Similarly, after this is called, any local and thread-local variables for the thread become invalid. So if a reference is made to them you can get a memory error.
If this has already been called for the thread (implicitly or explicitly) calling it again has an undefined behaviour, and
If this is the last thread in your process, this will cause the process to exit.
If you are careful of the above (i.e. if you are careful to not reference anything about the thread after you have called pthread_exit) then it is safe to call call manually. However, if you are using C++ instead of C I would highly recommend using the std::thread class rather than doing it manually. It is easier to read, involves less code, and ensures that you are not breaking any of the above.
For more information type "man pthread_exit" which will essentially tell you the above.
Since the question has now been changed, I will write a new answer. My answer still remains "yes and no" but the reasons have changed.
pthread_kill is somewhat dangerous in that it shares the potential timing risks that is inherent in all signal handling systems. In addition there are complexities in dealing with it, specifically you have to setup a signal handler within the thread. However one could argue that it is less dangerous than the Windows function you mention. Here is why:
The Windows function essentially stops the thread, possibly bypassing the proper cleanup. It is intended as a last resort option. pthread_kill, on the other hand, does not terminate the thread at all. It simply sends a signal to the thread that the thread can respond to.
In order for this to do something you need to have registered in the thread what signals you want it to handle. If your goal is to use pthread_kill to terminate the thread, you can use this by having your signal handler set a flag that the thread can access, and having the thread check the flag and exit when it gets set. You may be able to call pthread_exit from the signal handler (I've never tried that) but it strikes me as being a bad idea since the signal comes asynchronously, and your thread is not guaranteed to still be running. The flag option I mention solves this provided that the flag is not local to the thread, allowing the signal handler to set it even if the target thread has already exited. Of course if you are doing this, you don't really need pthread_kill at all, as you can simply have your main thread set the flag at the appropriate time.
There is another option for stopping another thread - the pthread_cancel method. This method will place a cancel request on the target thread and, if the thread has been configured to be cancellable (you generally do this in the pthread_create, but you can also do it after the fact), then the next time the thread reaches a potential cancellation point (specified by pthread_testcancel but also automatically handled by many system routines such as the IO calls), it will exit. This is also safer than what Windows does as it is not violently stopping the thread - it only stops at well defined points. But it is more work than the Windows version as you have to configure the thread properly.
The Wikipedia page for "posix threads" describes some of this (but not much), but it has a pretty good "See also" and "References" section that will give you more details.

Signalling a particular thread among many waiting on a condition variable

This question follows from Breaking a condition variable deadlock. A number of threads may be waiting on a condition variable, I need to signal only a particular thread say thread 1 and kill it as it was a participant of a deadlock scenario. Is there a way i could signal just a partipular thread amoung the lot.
Would be gratefull for some help
thanks
An Edit; Respecting Nemo's comments. I understand this is a bad idea. But, is there a way to do it
You can use deferred cancellation points. In your threads, use pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldstate); (this is the default, but it never hurts to be explicit); then disable cancellation with pthread_setcancelstate except for over the condition variable waits you want to be cancellable. Be sure that you use pthread_cleanup_push to set up cancellation cleanup handlers; this will NOT play nicely with RAII.
And now you can just pthread_cancel your thread. Cancellation cleanup handlers are executed, in reverse order of registration, TLS data destructors are called, and the thread exits (without returning from the condition variable wait).
Of course, this is a rather ugly design. Ideally you should avoid deadlocking at all; if that isn't possible, if it were me, I would arrange for only one thread to ever block on a single cvar at a time, and build a higher level (explicit waiter list) construct based on these cvars in order to handle multiple waiters, while still allowing for threads to be individually addressable.
Just write code to do exactly what you need. There's no shortcut since condition variables don't provide this behavior. So just write it. There's nothing difficult about it. For example, you could set a special flag, wake all threads blocked on the condition variable, and then code the threads to check the flag to see if there's supposed to go back to sleep or not.

signal handler in a thread

I am writing a multithreaded program and i have this question:
Suppose that, while executing in the main thread, i want to terminate all
child-threads. I can't just send them a termination signal cause i want them
to free dynamically allocated memory first. Can i define a specific signal handler
function in each thread function that is executed, which in turn is going to call
a cleanup function that i will write to do so? If not how can i accomplish my goal??
Thanks,
Nikos
Look at the man page for pthread_cancel:
When a cancellation requested is acted on, the following steps occur for
thread (in this order):
1. Cancellation clean-up handlers are popped (in the reverse of the order in
which they were pushed) and called. (See pthread_cleanup_push(3).)
2. Thread-specific data destructors are called, in an unspecified order. (See
pthread_key_create(3).)
3. The thread is terminated. (See pthread_exit(3).)
So you can use pthread_cancel from your main, provided you have registered you cleanup handlers correctly using the above functions.
(Do read that man page completely though, it has a lot of important information.)
Edit: (from comments) If you plan on using PTHREAD_CANCEL_DEFERRED and need to insert a cancellation point somewhere in your code, then use pthread_testcancel. This function checks if a cancellation was requested. If that is the case, the cancellation is serviced (i.e. that call never returns). Otherwise it has no effect.
The most robust strategy requires cooperation from the child threads: you set a flag that the threads periodically check and, when the flag is set, free whatever resources they're using and then terminate.
Cancellation (Mat's answer) is the correct and canonical one, but if you want a different approach, you can install a no-op signal handler using sigaction without the SA_RESTART flag and use pthread_kill with whatever signal number you chose in order to interrupt (EINTR) whatever the thread might have been blocked on. Combined with this, aix's answer works.

Resources