In my application the main thread creates two joined threads; one which waits for user input by calling scanf() in a loop and another one which listens for incoming socket connections by calling accept() in a loop. New connections are handled in separate threads which are detached.
I want the program to shut itself down gracefully when a SIGINT signal is received. That means that the listening thread should stop accepting new connections, wait for threads currently serving connections to close and then then. The thread waiting for user input should also end and thereby allowing the main thread to end.
Scanf() and accept() both block but can be interrupted by a signal, however signals sent to the process can only be handled by one thread (AFAIK). My idea is to block SIGINT signals in all threads except the main thread which will wait for it. When it receives a SIGINT, it will then send SIGUSR1 to the two threads (one which blocks on scanf() and one which blocks on accept()) and then join on these threads.
Is this a good solution? Is there a better or perhaps standard way to achieve this?
The pthread_exit() function terminates the calling thread, making its exit status available to any waiting threads. Normally, a thread terminates by returning from the start routine that was specified in the pthread_create() call which started it.
It is generally unsafe to provide slots in your QThread subclass, unless you protect the member variables with a mutex. On the other hand, you can safely emit signals from your QThread::run() implementation, because signal emission is thread-safe.
pthreads or POSIX threads are an implementation of the thread API for C/C++. It allows the spawning of new concurrent process flows and the multithreading system, which allows parallel and distributed processing. It does so by dividing the program into subtasks whose execution can be interleaved to run in parallel.
If any thread within a process calls exit, _Exit, or _exit, then the entire process terminates.
The canonical solution for problems like this is Thread Cancellation. A cancellation request that arrives while a thread is blocked in a function which is a cancellation point will be acted upon immediately; otherwise, it's acted upon the next time the thread calls a function that's a cancellation point.
The only thing that might be painful about using cancellation is that it's built on a model of exception handling rather than failure returns. You need to either keep cancellation blocked most of the time (and only enable it during operations during which you want to handle cancelling) or else install cancellation cleanup handlers (basically, semi-ugly exception handlers in C) at each call frame level where you might have intermediate state/allocations/etc. to clear out when your thread is cancelled. Personally I prefer the first approach, which generally only requires one cancellation handlers be installed.
Any approach based on interrupting signals inherently has race conditions. If the signal is sent just before the blocking function is called, then when the signal handler returns, the blocking function will be called and will block indefinitely (since the check for "is it time to exit?" was already successfully passed).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With