I'm having a little trouble with pthreads. Basically, I want to catch a SIGINT and have all threads cleanup and exit. What I have (skeleton code):
main.c:
sig_atomic_t running;
void handler(int signal_number)
{
running = 0;
}
int main(void)
{
queue job_queue = new_job_queue();
running = 1;
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = &handler;
sigaction(SIGINT, &sa, NULL);
/* create a bunch of threads */
init_threads(&job_queue);
while(running) {
/* do stuff */
}
cleanup();
return (0);
}
threads.c
extern sig_atomic_t running;
pthread_mutex_t queue_mutex = PTHREAD_MUTEX_INITIALIZER;
sem_t queue_count;
void init_threads(queue *q)
{
int numthreads = 12; /* say */
sem_init (&queue_count, 0, 0);
pthread_t worker_threads[numthreads];
int i;
for(i=0;i<numthreads;i++)
pthread_create(&worker_threads[i], NULL, &thread_function, q);
}
void * thread_function(void *args)
{
pthread_detatch(pthread_self());
queue *q = (queue *)args;
while(running) {
job *j = NULL;
sem_wait(&queue_count);
pthread_mutex_lock(&queue_mutex);
j = first_job_in_queue(q);
pthread_mutex_unlock(&queue_mutex);
if(j) {
/*do something*/
}
}
return (NULL);
}
I am having little luck with this. Since you're not guarenteed which thread gets the signal I thought this was a good way to go. But I am having a problem where sem_wait() in threads.c is hanging, which is expected but not desired. The while(running) loop in threads.c seems redundant. Should I maybe do a pthread_kill() to all the threads from main? Any obvious problems with the above skeleton code? Is there a better/easier way to go about doing this?
Thanks.
What you can do is to call sem_post() from the handler until all threads are unlocked. In the thread function, immediately after sem_wait() you should check the value of the running variable and if it's zero break breom the while.
The code in the handler could be something like the following:
int sval;
sem_getvalue(&queue_count, &sval);
while (sval < 0) {
sem_post(&queue_count);
sem_getvalue(&queue_count, &sval);
}
Of course return values should be verified for errors
You can catch SIGINT in one thread, and use pthread_sigmask() to block SIGINT in all other threads, if SIGINT generated by some way, the signal will be delivered to the specified thread, that thread can call pthread_cancel() to cancel all other threads.
You may want to consider calling pthread_join after each call to pthread_create. This will allow for your main thread to wait until all threads are done executing.
But maybe I'm misunderstanding slightly... Do you want to wait for all threads to finish, or simply wait for one to finish, and then stop all others immediately?
You shouldn't do a pthread_kill() if you don't have to. I'm not to familiar with pthread_detatch() but if you are wanting your main() function to wait for the threads to finish, it would probably be better if your cleanup() function did a pthread_join() on each thread id returned from pthread_create() to wait for each thread to exit normally.
Also, as far as I can tell, sem_wait() is hanging because your semaphore value is initialized to 0. If you want say at most 5 threads to access the shared resource at a time, initialize the semaphore to 5, i.e. sem_init(&queue_count, 0, 5).
Related
#include <stdio.h>
#include <pthread.h>
#include <signal.h>
sigset_t set;
int sigint_signal = 0;
pthread_t monitor_thread, demo_thread;
pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
void *monitor()
{
while(1)
{
sigwait(&set, NULL);
pthread_mutex_lock(&m);
printf("__SIGINT received__\n");
sigint_signal = 1;
pthread_cancel(demo_thread);
pthread_mutex_unlock(&m);
}
}
void *demo_function(){
while(1){
pthread_mutex_lock(&m);
fprintf(stdout, "__Value of SIGNAL FLAG %d:__\n",sigint_signal);
pthread_mutex_unlock(&m);
}
return NULL;
}
int main(){
sigemptyset(&set);
sigaddset(&set,SIGINT);
pthread_sigmask(SIG_BLOCK,&set,0);
pthread_create(&monitor_thread, 0, monitor, NULL);
pthread_create(&demo_thread, 0, demo_function, NULL);
pthread_join(demo_thread, NULL);
return 0;
}
monitor_thread is the thread that is continuously running to catch the SIGINT signal. On receiving the signal it must cancel the other thread and end.
SIGINT is getting received, this can be verified with the value of the variable sigint_signal which becomes 1 once the signal is received.But pthread_cancel is not getting executed, because once the value of sigint_signal is changed to 1, the demo_thread keeps on running.Please help.
Read the documentation: http://man7.org/linux/man-pages/man3/pthread_cancel.3.html
There you will see that pthread_cancel is not guaranteed to instantly kill the thread, but rather that it depends on the state of that thread. By default, cancellation can only occur at cancellation points, which do include write() which may indirectly include printf().
Anyway, the real solution is to not use pthread_cancel at all, and instead use sigint_signal as the while loop condition in demo_function.
As for why pthread_cancel is a bad idea, this is because in general, functions are usually not written in a way that they are prepared to die. It's hard to reason about resource management in a context where execution might be terminated asynchronously.
I am trying to write a code that does not block main() when pthread_join() is called:
i.e. basically trying to implement my previous question mentioned below:
https://stackoverflow.com/questions/24509500/pthread-join-and-main-blocking-multithreading
And the corresponding explanation at:
pthreads - Join on group of threads, wait for one to exit
As per suggested answer:
You'd need to create your own version of it - e.g. an array of flags (one flag per thread) protected by a mutex and a condition variable; where just before "pthread_exit()" each thread acquires the mutex, sets its flag, then does "pthread_cond_signal()". The main thread waits for the signal, then checks the array of flags to determine which thread/s to join (there may be more than one thread to join by then).
I have tried as below:
My status array which keeps a track of which threads have finished:
typedef struct {
int Finish_Status[THREAD_NUM];
int signalled;
pthread_mutex_t mutex;
pthread_cond_t FINISHED;
}THREAD_FINISH_STATE;
The thread routine, it sets the corresponding array element when the thread finishes and also signals the condition variable:
void* THREAD_ROUTINE(void* arg)
{
THREAD_ARGUMENT* temp=(THREAD_ARGUMENT*) arg;
printf("Thread created with id %d\n",temp->id);
waitFor(5);
pthread_mutex_lock(&(ThreadFinishStatus.mutex));
ThreadFinishStatus.Finish_Status[temp->id]=TRUE;
ThreadFinishStatus.signalled=TRUE;
if(ThreadFinishStatus.signalled==TRUE)
{
pthread_cond_signal(&(ThreadFinishStatus.FINISHED));
printf("Signal that thread %d finished\n",temp->id);
}
pthread_mutex_unlock(&(ThreadFinishStatus.mutex));
pthread_exit((void*)(temp->id));
}
I am not able to write the corresponding parts pthread_join() and pthread_cond_wait() functions. There are a few things which I am not able to implement.
1) How to write corresponding part pthread_cond_wait() in my main()?
2) I am trying to write it as:
pthread_mutex_lock(&(ThreadFinishStatus.mutex));
while((ThreadFinishStatus.signalled != TRUE){
pthread_cond_wait(&(ThreadFinishStatus.FINISHED), &(ThreadFinishStatus.mutex));
printf("Main Thread signalled\n");
ThreadFinishStatus.signalled==FALSE; //Reset signalled
//check which thread to join
}
pthread_mutex_unlock(&(ThreadFinishStatus.mutex));
But it does not enter the while loop.
3) How to use pthread_join() so that I can get the return value stored in my arg[i].returnStatus
i.e. where to put below statement in my main:
`pthread_join(T[i],&(arg[i].returnStatus));`
COMPLETE CODE
#include <stdio.h>
#include <pthread.h>
#include <time.h>
#define THREAD_NUM 5
#define FALSE 0
#define TRUE 1
void waitFor (unsigned int secs) {
time_t retTime;
retTime = time(0) + secs; // Get finishing time.
while (time(0) < retTime); // Loop until it arrives.
}
typedef struct {
int Finish_Status[THREAD_NUM];
int signalled;
pthread_mutex_t mutex;
pthread_cond_t FINISHED;
}THREAD_FINISH_STATE;
typedef struct {
int id;
void* returnStatus;
}THREAD_ARGUMENT;
THREAD_FINISH_STATE ThreadFinishStatus;
void initializeState(THREAD_FINISH_STATE* state)
{
int i=0;
state->signalled=FALSE;
for(i=0;i<THREAD_NUM;i++)
{
state->Finish_Status[i]=FALSE;
}
pthread_mutex_init(&(state->mutex),NULL);
pthread_cond_init(&(state->FINISHED),NULL);
}
void destroyState(THREAD_FINISH_STATE* state)
{
int i=0;
for(i=0;i<THREAD_NUM;i++)
{
state->Finish_Status[i]=FALSE;
}
pthread_mutex_destroy(&(state->mutex));
pthread_cond_destroy(&(state->FINISHED));
}
void* THREAD_ROUTINE(void* arg)
{
THREAD_ARGUMENT* temp=(THREAD_ARGUMENT*) arg;
printf("Thread created with id %d\n",temp->id);
waitFor(5);
pthread_mutex_lock(&(ThreadFinishStatus.mutex));
ThreadFinishStatus.Finish_Status[temp->id]=TRUE;
ThreadFinishStatus.signalled=TRUE;
if(ThreadFinishStatus.signalled==TRUE)
{
pthread_cond_signal(&(ThreadFinishStatus.FINISHED));
printf("Signal that thread %d finished\n",temp->id);
}
pthread_mutex_unlock(&(ThreadFinishStatus.mutex));
pthread_exit((void*)(temp->id));
}
int main()
{
THREAD_ARGUMENT arg[THREAD_NUM];
pthread_t T[THREAD_NUM];
int i=0;
initializeState(&ThreadFinishStatus);
for(i=0;i<THREAD_NUM;i++)
{
arg[i].id=i;
}
for(i=0;i<THREAD_NUM;i++)
{
pthread_create(&T[i],NULL,THREAD_ROUTINE,(void*)&arg[i]);
}
/*
Join only if signal received
*/
pthread_mutex_lock(&(ThreadFinishStatus.mutex));
//Wait
while((ThreadFinishStatus.signalled != TRUE){
pthread_cond_wait(&(ThreadFinishStatus.FINISHED), &(ThreadFinishStatus.mutex));
printf("Main Thread signalled\n");
ThreadFinishStatus.signalled==FALSE; //Reset signalled
//check which thread to join
}
pthread_mutex_unlock(&(ThreadFinishStatus.mutex));
destroyState(&ThreadFinishStatus);
return 0;
}
Here is an example of a program that uses a counting semaphore to watch as threads finish, find out which thread it was, and review some result data from that thread. This program is efficient with locks - waiters are not spuriously woken up (notice how the threads only post to the semaphore after they've released the mutex protecting shared state).
This design allows the main program to process the result from some thread's computation immediately after the thread completes, and does not require the main wait for all threads to complete. This would be especially helpful if the running time of each thread varied by a significant amount.
Most importantly, this program does not deadlock nor race.
#include <pthread.h>
#include <semaphore.h>
#include <stdlib.h>
#include <stdio.h>
#include <queue>
void* ThreadEntry(void* args );
typedef struct {
int threadId;
pthread_t thread;
int threadResult;
} ThreadState;
sem_t completionSema;
pthread_mutex_t resultMutex;
std::queue<int> threadCompletions;
ThreadState* threadInfos;
int main() {
int numThreads = 10;
int* threadResults;
void* threadResult;
int doneThreadId;
sem_init( &completionSema, 0, 0 );
pthread_mutex_init( &resultMutex, 0 );
threadInfos = new ThreadState[numThreads];
for ( int i = 0; i < numThreads; i++ ) {
threadInfos[i].threadId = i;
pthread_create( &threadInfos[i].thread, NULL, &ThreadEntry, &threadInfos[i].threadId );
}
for ( int i = 0; i < numThreads; i++ ) {
// Wait for any one thread to complete; ie, wait for someone
// to queue to the threadCompletions queue.
sem_wait( &completionSema );
// Find out what was queued; queue is accessed from multiple threads,
// so protect with a vanilla mutex.
pthread_mutex_lock(&resultMutex);
doneThreadId = threadCompletions.front();
threadCompletions.pop();
pthread_mutex_unlock(&resultMutex);
// Announce which thread ID we saw finish
printf(
"Main saw TID %d finish\n\tThe thread's result was %d\n",
doneThreadId,
threadInfos[doneThreadId].threadResult
);
// pthread_join to clean up the thread.
pthread_join( threadInfos[doneThreadId].thread, &threadResult );
}
delete threadInfos;
pthread_mutex_destroy( &resultMutex );
sem_destroy( &completionSema );
}
void* ThreadEntry(void* args ) {
int threadId = *((int*)args);
printf("hello from thread %d\n", threadId );
// This can safely be accessed since each thread has its own space
// and array derefs are thread safe.
threadInfos[threadId].threadResult = rand() % 1000;
pthread_mutex_lock( &resultMutex );
threadCompletions.push( threadId );
pthread_mutex_unlock( &resultMutex );
sem_post( &completionSema );
return 0;
}
Pthread conditions don't have "memory"; pthread_cond_wait doesn't return if pthread_cond_signal is called before pthread_cond_wait, which is why it's important to check the predicate before calling pthread_cond_wait, and not call it if it's true. But that means the action, in this case "check which thread to join" should only depend on the predicate, not on whether pthread_cond_wait is called.
Also, you might want to make the while loop actually wait for all the threads to terminate, which you aren't doing now.
(Also, I think the other answer about "signalled==FALSE" being harmless is wrong, it's not harmless, because there's a pthread_cond_wait, and when that returns, signalled would have changed to true.)
So if I wanted to write a program that waited for all threads to terminate this way, it would look more like
pthread_mutex_lock(&(ThreadFinishStatus.mutex));
// AllThreadsFinished would check that all of Finish_Status[] is true
// or something, or simpler, count the number of joins completed
while (!AllThreadsFinished()) {
// Wait, keeping in mind that the condition might already have been
// signalled, in which case it's too late to call pthread_cond_wait,
// but also keeping in mind that pthread_cond_wait can return spuriously,
// thus using a while loop
while (!ThreadFinishStatus.signalled) {
pthread_cond_wait(&(ThreadFinishStatus.FINISHED), &(ThreadFinishStatus.mutex));
}
printf("Main Thread signalled\n");
ThreadFinishStatus.signalled=FALSE; //Reset signalled
//check which thread to join
}
pthread_mutex_unlock(&(ThreadFinishStatus.mutex));
Your code is racy.
Suppose you start a thread and it finishes before you grab the mutex in main(). Your while loop will never run because signalled was already set to TRUE by the exiting thread.
I will echo #antiduh's suggestion to use a semaphore that counts the number of dead-but-not-joined threads. You then loop up to the number of threads spawned waiting on the semaphore. I'd point out that the POSIX sem_t is not like a pthread_mutex in that sem_wait can return EINTR.
Your code appears fine. You have one minor buglet:
ThreadFinishStatus.signalled==FALSE; //Reset signalled
This does nothing. It tests whether signalled is FALSE and throws away the result. That's harmless though since there's nothing you need to do. (You never want to set signalled to FALSE because that loses the fact that it was signalled. There is never any reason to unsignal it -- if a thread finished, then it's finished forever.)
Not entering the while loop means signalled is TRUE. That means the thread already set it, in which case there is no need to enter the loop because there's nothing to wait for. So that's fine.
Also:
ThreadFinishStatus.signalled=TRUE;
if(ThreadFinishStatus.signalled==TRUE)
There's no need to test the thing you just set. It's not like the set can fail.
FWIW, I would suggest re-architecting. If the existing functions like pthread_join don't do exactly what you want, just don't use them. If you're going to have structures that track what work is done, then totally separate that from thread termination. Since you will already know what work is done, what different does it make when and how threads terminate? Don't think of this as "I need a special way to know when a thread terminates" and instead think of this "I need to know what work is done so I can do other things".
I have a C program in which I use pthread.
I would like newly created threads to run as soon as they are created.
The reason behind this is that my threads have initialisation code to set up signal handlers, and I must be sure the handlers are ready, before my main thread sends some signals.
I've tried doing pthread_yield just after my pthread_create, but without success.
I doubt it makes a difference, but I am running Linux 3.6 on x86_64.
Thanks
If your goal is to have the main thread wait for all threads to reach the same point before continuing onward, I would suggest using pthread_barrier_wait:
void worker(void*);
int main(int argc, char **argv)
{
pthread_barrier_t b;
pthread_t children[TCOUNT];
int child;
/* +1 for our main thread */
pthread_barrier_init(&b, NULL, TCOUNT+1);
for (child = 0; child < TCOUNT; ++child)
{
pthread_create(&children[child], NULL, worker, &b);
}
printf("main: children created\n");
/* everybody who calls barrier_wait will wait
* until TCOUNT+1 have called it
*/
pthread_barrier_wait(&b);
printf("main: children finished\n");
/* wait for children to finish */
for (child = 0; child < TCOUNT; ++child)
{
pthread_join(&children[child], NULL);
}
/* clean-up */
pthread_barrier_destroy(&b);
return 0;
}
void worker(void *_b)
{
pthread_barrier_t *b = (pthread_barrier_t*)_b;
printf("child: before\n");
pthread_barrier_wait(b);
printf("child: after\n");
}
Or you might use a barrier, i.e. call pthread_barrier_wait (early in the routine of each thread, or at initialization in the main thread), to ensure that every relevant thread has reached the barrier (after which some of your threads could do your naughty signal tricks). See this question.
I am trying to figure out how to get rid of a reliance on the pthread_timedjoin_np because I am trying to build some code on OSX.
Right now I have a Queue of threads that I am popping from, doing that pthread_timedjoin_np and if they dont return, they get pushed back on the queue.
The end of the thread_function that is called for each thread does a pthread_exit(0); so that the recieving thread can check for a return value of zero.
I thought i might try to use pthread_cond_timedwait() to achieve a similar effect, however I think i am missing a step.
I thought I would be able to make worker Thread A signal a condition AND pthread_exit() within a mutex, , and worker Thread B could wake up on the signal, and then pthread_join(). The problem is, Thread B doesn't know which thread threw the conditional signal. Do I need to explicitly pass that as part of the conditonal signal or what?
Thanks
Derek
Here is a portable implementation of pthread_timedjoin_np. It's a bit costly, but it's a full drop-in replacement:
struct args {
int joined;
pthread_t td;
pthread_mutex_t mtx;
pthread_cond_t cond;
void **res;
};
static void *waiter(void *ap)
{
struct args *args = ap;
pthread_join(args->td, args->res);
pthread_mutex_lock(&args->mtx);
args->joined = 1;
pthread_mutex_unlock(&args->mtx);
pthread_cond_signal(&args->cond);
return 0;
}
int pthread_timedjoin_np(pthread_t td, void **res, struct timespec *ts)
{
pthread_t tmp;
int ret;
struct args args = { .td = td, .res = res };
pthread_mutex_init(&args.mtx, 0);
pthread_cond_init(&args.cond, 0);
pthread_mutex_lock(&args.mtx);
ret = pthread_create(&tmp, 0, waiter, &args);
if (!ret)
do ret = pthread_cond_timedwait(&args.cond, &args.mtx, ts);
while (!args.joined && ret != ETIMEDOUT);
pthread_mutex_unlock(&args.mtx);
pthread_cancel(tmp);
pthread_join(tmp, 0);
pthread_cond_destroy(&args.cond);
pthread_mutex_destroy(&args.mtx);
return args.joined ? 0 : ret;
}
There may be small errors since I wrote this on the spot and did not test it, but the concept is sound.
Producer-consumer queue. Have the threads queue *themselves, and so their results,(if any), to the queue before they exit. Wait on the queue.
No polling, no latency.
With your current design, you would have to join() the returned threads get the valueptr and to ensure that they are destroyed.
Maybe you could sometime move to a real threadpool, where task items are queued to threads that never terminate, (so eliminating thread create/terminate/destroy overhead)?
solution with alarm.
pthread should enable cancel, so it can stop by external.(even with pthread_timedjoin_np).
pthread_timedjoin_np return with ETIMEOUT after waited time.
set alarm, use alarm also can give "TIMEOUT" signal.
In handler, just pthread_cancel it. (only timeout run this).
pthread_join it in main thread.
reset alarm
I write test code in here:github
I have to code a multithreaded(say 2 threads) program where each of these threads do a different task. Also, these threads must keep running infinitely in the background once started. Here is what I have done. Can somebody please give me some feedback if the method is good and if you see some problems. Also, I would like to know how to shut the threads in a systematic way once I terminate the execution say with Ctrl+C.
The main function creates two threads and let them run infinitely as below.
Here is the skeleton:
void *func1();
void *func2();
int main(int argc, char *argv[])
{
pthread_t th1,th2;
pthread_create(&th1, NULL, func1, NULL);
pthread_create(&th2, NULL, func2, NULL);
fflush (stdout);
for(;;){
}
exit(0); //never reached
}
void *func1()
{
while(1){
//do something
}
}
void *func2()
{
while(1){
//do something
}
}
Thanks.
Edited code using inputs from the answers:
Am I exiting the threads properly?
#include <stdlib.h> /* exit() */
#include <stdio.h> /* standard in and output*/
#include <pthread.h>
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#include <signal.h>
#include <semaphore.h>
sem_t end;
void *func1();
void *func2();
void ThreadTermHandler(int signo){
if (signo == SIGINT) {
printf("Ctrl+C detected !!! \n");
sem_post(&end);
}
}
void *func1()
{
int value;
for(;;){
sem_getvalue(&end, &value);
while(!value){
printf("in thread 1 \n");
}
}
return 0;
}
void *func2()
{
int value;
for(;;){
sem_getvalue(&end, &value);
while(!value){
printf("value = %d\n", value);
}
}
return 0;
}
int main(int argc, char *argv[])
{
sem_init(&end, 0, 0);
pthread_t th1,th2;
int value = -2;
pthread_create(&th1, NULL, func1, NULL);
pthread_create(&th2, NULL, func2, NULL);
struct sigaction sa;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = ThreadTermHandler;
// Establish a handler to catch CTRL+c and use it for exiting.
if (sigaction(SIGINT, &sa, NULL) == -1) {
perror("sigaction for Thread Termination failed");
exit( EXIT_FAILURE );
}
/* Wait for SIGINT. */
while (sem_wait(&end)!=0){}
//{
printf("Terminating Threads.. \n");
sem_post(&end);
sem_getvalue(&end, &value);
/* SIGINT received, cancel threads. */
pthread_cancel(th1);
pthread_cancel(th2);
/* Join threads. */
pthread_join(th1, NULL);
pthread_join(th2, NULL);
//}
exit(0);
}
There are mainly two approaches for thread termination.
Use a cancellation point. The thread will terminate when requested to cancel and it reaches a cancellation point, thus ending execution in a controlled fashion;
Use a signal. Have the threads install a signal handler which provides a mechanism for termination (setting a flag and reacting to EINTR).
Both approaches has caveats. Refer to Kill Thread in Pthread Library for more details.
In your case, it seems a good opportunity to use cancellation points. I will work with a commented example. The error-checking has been omitted for clarity.
#define _POSIX_C_SOURCE 200809L
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void sigint(int signo) {
(void)signo;
}
void *thread(void *argument) {
(void)argument;
for (;;) {
// Do something useful.
printf("Thread %u running.\n", *(unsigned int*)argument);
// sleep() is a cancellation point in this example.
sleep(1);
}
return NULL;
}
int main(void) {
// Block the SIGINT signal. The threads will inherit the signal mask.
// This will avoid them catching SIGINT instead of this thread.
sigset_t sigset, oldset;
sigemptyset(&sigset);
sigaddset(&sigset, SIGINT);
pthread_sigmask(SIG_BLOCK, &sigset, &oldset);
// Spawn the two threads.
pthread_t thread1, thread2;
pthread_create(&thread1, NULL, thread, &(unsigned int){1});
pthread_create(&thread2, NULL, thread, &(unsigned int){2});
// Install the signal handler for SIGINT.
struct sigaction s;
s.sa_handler = sigint;
sigemptyset(&s.sa_mask);
s.sa_flags = 0;
sigaction(SIGINT, &s, NULL);
// Restore the old signal mask only for this thread.
pthread_sigmask(SIG_SETMASK, &oldset, NULL);
// Wait for SIGINT to arrive.
pause();
// Cancel both threads.
pthread_cancel(thread1);
pthread_cancel(thread2);
// Join both threads.
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
// Done.
puts("Terminated.");
return EXIT_SUCCESS;
}
The need for blocking/unblocking signals is that if you send SIGINT to the process, any thread may be able to catch it. You do so before spawning the threads to avoid having them doing it by themselves and needing to synchronize with the parent. After the threads are created, you restore the mask and install a handler.
Cancellation points can be tricky if the threads allocates a lot of resources; in that case, you will have to use pthread_cleanup_push() and pthread_cleanup_pop(), which are a mess. But the approach is feasible and rather elegant if used properly.
The answer depends a lot on what you want to do when the user presses CtrlC.
If your worker threads are not modifying data that needs to be saved on exit, you don't need to do anything. The default action of SIGINT is to terminate the process, and that includes all threads that make up the process.
If your threads do need to perform cleanup, however, you've got some work to do. There are two separate issues you need to consider:
How you handle the signal and get the message to threads that they need to terminate.
How your threads receive and handle the request to terminate.
First of all, signal handlers are a pain. Unless you're very careful, you have to assume most library functions are not legal to call from a signal handler. Fortunately, sem_post is specified to be async-signal-safe, and can meet your requirements perfectly:
At the beginning of your program, initialize a semaphore with sem_init(&exit_sem, 0, 0);
Install a signal handler for SIGINT (and any other termination signals you want to handle, like SIGTERM) that performs sem_post(&exit_sem); and returns.
Replace the for(;;); in the main thread with while (sem_wait(&exit_sem)!=0).
After sem_wait succeeds, the main thread should inform all other threads that they should exit, then wait for them all to exit.
The above can also be accomplished without semaphores using signal masks and sigwaitinfo, but I prefer the semaphore approach because it doesn't require you to learn lots of complicated signal semantics.
Now, there are several ways you could handle informing the worker threads that it's time to quit. Some options I see:
Having them check sem_getvalue(&exit_sem) periodically and cleanup and exit if it returns a nonzero value. Note however that this will not work if the thread is blocked indefinitely, for example in a call to read or write.
Use pthread_cancel, and carefully place cancellation handlers (pthread_cleanup_push) all over the place.
Use pthread_cancel, but also use pthread_setcancelstate to disable cancellation during most of your code, and only re-enable it when you're going to perform blocking IO operations. This way you need only put the cleanup handlers just in the places where cancellation is enabled.
Learn advanced signal semantics, and setup an additional signal and interrupting signal handler which you send to all threads via pthread_kill which will cause blocking syscalls to return with an EINTR error. Then your threads can act on this and exit the normal C way via a string of failure returns all the way back up the the start function.
I would not recommend approach 4 for beginners, because it's hard to get right, but for advanced C programmers it may be the best because it allows you to use the existing C idiom of reporting exceptional conditions via return values rather than "exceptions".
Also note that with pthread_cancel, you will need to periodically call pthread_testcancel if you are not calling any other functions which are cancellation points. Otherwise the cancellation request will never be acted upon.
This is a bad idea:
for(;;){
}
because your main thread will execute unnecessary CPU instructions.
If you need to wait in the main thread, use pthread_join as answered in this question: Multiple threads in C program
What you have done works, I see no obvious problems with it (except that you are ignoring the return value of pthread_create). Unfortunately, stopping threads is more involved than you might think. The fact that you want to use signals is another complication. Here's what you could do.
In the "children" threads, use pthread_sigmask to block signals
In the main thread, use sigsuspend to wait for a signal
Once you receive the signal, cancel (pthread_cancel) the children threads
Your main thread could look something like this:
/* Wait for SIGINT. */
sigsuspend(&mask);
/* SIGINT received, cancel threads. */
pthread_cancel(th1);
pthread_cancel(th2);
/* Join threads. */
pthread_join(th1, NULL);
pthread_join(th2, NULL);
Obviously, you should read more about pthread_cancel and cancellation points. You could also install a cleanup handler. And of course, check every return value.
Looked at your updated coded and it still does not look right.
Signal handling must be done in only one thread. Signals targeted for a process (such as SIGINT) get delivered to any thread that does not have that signal blocked. In other words, there is no guarantee that given the three threads you have it is going to be the main thread that receives SIGINT. In multi-threaded programs the best practise is too block all signals before creating any threads, and once all threads have been created unblock the signals in the main thread only (normally it is the main thread that is in the best position to handle signals). See Signal Concepts and Signalling in a Multi-Threaded Process for more.
pthread_cancel is best avoided, there no reason to ever use it. To stop the threads you should somehow communicate to them that they should terminate and wait till they have terminated voluntarily. Normally, the threads will have some sort of event loop, so it should be relatively straightforward to send the other thread an event.
Wouldn't it be much easier to just call pthread_cancel and use pthread_cleanup_push in the thread function to potentially clean up the data that was dynamically allocated by the thread or do any termination tasks that was required before the thread stops.
So the idea would be:
write the code to handle signals
when you do ctrl+c ... the handling function is called
this function cancels the thread
each thread which was created set a thread cleanup function using pthread_cleanup_push
when the tread is cancelled the pthread_cleanup_push's function is called
join all threads before exiting
It seems like a simple and natural solution.
static void cleanup_handler(void *arg)
{
printf("Called clean-up handler\n");
}
static void *threadFunc(void *data)
{
ThreadData *td = (ThreadData*)(data);
pthread_cleanup_push(cleanup_handler, (void*)something);
while (1) {
pthread_testcancel(); /* A cancellation point */
...
}
pthread_cleanup_pop(cleanup_pop_arg);
return NULL;
}
You don't need the foor loop in the main. A th1->join(); th2->join(); will suffice as a wait condition since the threads never end.
To stop the threads you could use a global shared var like bool stop = false;, then when catching the signal (Ctrl+Z is a signal in UNIX), set stop = true aborting the threads, since you are waiting with join() the main program will also exit.
example
void *func1(){
while(!stop){
//do something
}
}