Is it possible to have an infinite loop in pthread? - c

I am doing a project with pthreads and I can not go further. I have 3 threads, one thread shall read some sensor values via I2C (SMBUS), one shall calculate something by using the data porvided by the first thread, and finally last thread shall print the data on screen. A mutex shall be responsible for the synchronisation between threads. How can I use infinite while loop in threads, since my threads don't just "do the job and finish"? They shall continue forever (or untill Ctrl+C key is pressed).
And where should I put the pthread_join functions?
My first approach is below but it is not working properly:
Thanks for your help.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <linux/i2c-dev.h>
#include <fcntl.h>
typedef struct vector {
double x;
double y;
double z;
} vector_t;
typedef struct all_vectors {
vector_t *gyro;
vector_t *accel;
vector_t *magnet;
} vectors_t;
vectors_t *vectors;
pthread_t th1, th2, th3;
pthread_mutex_t mutex;
int main()
{
initSensors(); //defined in another .c file
pthread_mutex_init(&mutex, NULL);
pthread_create(&th1, NULL, (void *) &readSensors, (void *) vectors);
pthread_create(&th2, NULL, (void *) &calculateAngle, NULL);
pthread_create(&th3, NULL, (void *) &printData, NULL);
while(1)
{
sleep(1);
}
/* The program never reaches the following codes ? */
pthread_mutex_destroy(&mutex);
pthread_exit(NULL);
}
void readSensors(void *vectors)
{
vectors_t *vecs = (vectors_t *)vectors;
while(1)
{
pthread_mutex_trylock(&mutex);
readGyro(vecs->gyro); //defined in another .c file
readAccel(vecs->accel); //defined in another .c file
readMagnet(vecs->magnet); //defined in another .c file
pthread_mutex_unlock(&mutex);
}
pthread_exit(NULL);
}
void calculateAngle()
{
while(1)
{
pthread_mutex_trylock(&mutex);
doSomeCalculation(vectors); //defined in another .c file
pthread_mutex_unlock(&mutex);
}
pthread_exit(NULL);
}
void printData()
{
while(1)
{
pthread_mutex_trylock(&mutex);
printf("%lf, %lf, %lf, lf, %lf, %lf, lf, %lf, %lf", \
vectors->accel->x, vectors->accel->y, vectors->accel->z, \
vectors->gyro->x, vectors->gyro->y, vectors->gyro->z, \
vectors->magnet->x, vectors->magnet->y, vectors->magnet->z );
pthread_mutex_unlock(&mutex);
fflush(stdout);
}
pthread_exit(NULL);
}

You seem surprised that code after this infinite loop
while(1)
{
sleep(1);
}
is not executed. Even if the code could reach this line
pthread_mutex_destroy(&mutex);
you would have problems because the threads are still using the mutex. If you want a graceful shutdown of your code I would add a global boolean that you loop over while true in your threads, then add a SIGINT handler to set this to false so that the threads can exit. Then in main, remove that infinite while loop and make calls to pthread_join on each thread before finally destroying the mutex and finally exiting main().
The pthread_join calls will block until the threads exit so your main() loop is not needed. The threads will exit gracefully on SIGINT and the program should run and terminate in a clean fashion.
One final observation: since vectors is a global variable you don't need to pass it to the thread via the void* argument since it is already visible.

You could have infinite loops, but as you have detected that would mean that the only way to exit the program would be via an interrupt, which would not allow the program to clean up properly.
If you want it to clean up (including joining the threads etc) then you need to provide a way that the loops can exit. One way could be a shared variable which would be set in response to some event and be in the condition for each loop so that once set all of the threads will exit.
You could set a signal handler for SIGINT to catch the ctrl-c and set the shared variable.
You call pthread_join from your main () to wait for the threads to exit. You do not need a loop in main, it will wait until the threads you are joining are done.

Related

How to solve race condition?

Value of Global variable var in main() function sometimes comes -1 and sometimes 1 .How to write a robust code without using sleep function so that thread get time to get started and running .
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
int var = -1; // GLobal Variable
void *myThreadFun(void *vargp)
{
var = 1;
return NULL;
}
int main()
{
pthread_t thread_id;
printf("Before Thread\n");
pthread_create(&thread_id, NULL, myThreadFun, NULL);
printf("var=%d",var);
pthread_join(thread_id, NULL);
printf("After Thread\n");
exit(0);
}
Value of Global variable var in main() function sometimes comes -1 and
sometimes 1 .How to write a robust code without using sleep function
so that thread get time to get started and running .
It is a distressingly common misconception among those new to multithreaded programming that problems such as yours are a matter of timing. That is not the case, at least not from the perspective of the threading and memory models of most modern high-level programming languages. No amount of delay alone ensures that one thread will see the effects on memory produced by another, therefore robust code does not use timing functions such as sleep() for that purpose.
Rather, the issue is one of synchronization. This is the area that contains rules about what writes to memory by one thread must be visible to other threads. It also covers special kinds of objects and functions that serve to enable threads to affect the execution of other threads, generally by temporarily blocking them from proceeding. These two facets are closely linked.
The pthread_create() and pthread_join() functions have synchronization effects. Among other things, all writes to memory by a thread T1 before it calls pthread_create() to start a thread T2 are visible to T2 (modulo subsequent rewrites of the same memory). All writes to memory by T2 are visible to T1 after it successfully joins T2 via pthread_join(). Therefore, one solution to the question as posed is to wait until after joining the second thread before attempting to read var, as #Robert's answer suggests.
If that is undesirable, then you'll need to engage some other kind of synchronization mechanism to make the main thread wait for the second to update var. Such a wait on a synchronization object will also have the effect of making the second thread's write visible to the main thread.
The most general-purpose synchronization technique offered by pthreads is the condition variable which must be used in conjunction with a mutex. You will find many explanations here on SO and elsewhere about how properly to use a CV.
For your particular case, however, you might find a semaphore easier to set up and use. Semaphores are technically separate from the pthreads library proper, but they have suitable synchronization semantics, both for making threads wait and for making memory operations of one thread visible to another. That might look like this:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
int var = -1; // GLobal Variable
sem_t semaphore;
void *myThreadFun(void *vargp)
{
var = 1;
// increment the semaphore's value
sem_post(&semaphore);
return NULL;
}
int main()
{
pthread_t thread_id;
// initialize the semaphore with value 0
sem_init(&semaphore, 0, 0);
printf("Before Thread\n");
pthread_create(&thread_id, NULL, myThreadFun, NULL);
// Wait until the semaphore's value can be decremented by one without
// it becoming negative (and then perform the decrement before proceeding).
sem_wait(&semaphore);
printf("var=%d",var);
pthread_join(thread_id, NULL);
printf("After Thread\n");
exit(0);
}
I think your code is robust, it's just where you print the result which is incorrect. You need to ensure your thread has finished his work before printing the result.
If you print the result before calling pthread_join, there are two possibilities:
myThreadFun has already changed var, in such case var will contain the value 1
myThreadFun hasn't been completely executed, in such case, var will have its initial value -1.
If you print the result after calling pthread_join, the function myThreadFun will be fully executed and it will print 1.
int main()
{
pthread_t thread_id;
printf("Before Thread\n");
pthread_create(&thread_id, NULL, myThreadFun, NULL);
pthread_join(thread_id, NULL);
printf("After Thread\n");
printf("var=%d",var); /* Here, the thread has completed */
exit(0);
}
Robert's solution is sensible, but I believe you don't actually want to wait for the thread to complete.
If you want the main thread to wait for the variable to be set by the thread without waiting for the thread to end, you will need some kind of synchronization. I'll use a semaphore, but there are a number of other solutions.
#include <pthread.h>
#include <stdio.h>
#include <semaphore.h>
#include <stdlib.h>
#include <unistd.h>
static sem_t started_threads_sem;
static int var;
static void *myThreadFun(void *vargp) {
sleep(3); // This is the thread doing some initialization.
var = 1;
sem_post(&started_threads_sem);
sleep(3); // This is the thread doing stuff.
return NULL;
}
int main() {
printf("Before Thread\n");
sem_init(&started_threads_sem, 0, 0);
pthread_t thread_id;
pthread_create(&thread_id, NULL, myThreadFun, NULL);
// Wait for the thread to have started.
sem_wait(&started_threads_sem);
printf("var=%d\n", var);
pthread_join(thread_id, NULL);
printf("After Thread\n");
exit(0);
}
Before Thread
<3 s pause>
var=1
<3 s pause>
After Thread

C print ping-pong using semaphores and threads

I am not sure I understand semaphores and threads so I decided to try a relatively simple example. I am trying to have 2 threads that will alternate printing, one printing "ping" the other printing "pong" each notifying the other that it is done by use of a semaphore. But when I implement the code below, it prints ping several hundred times followed by pong several hundred times with a slight pause.
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
sem_t pingsem;
void ping(){
printf("Ping started\n");
while(1){
sem_wait(&pingsem);
printf("ping\n");
sem_post(&pingsem);
}
}
void pong(){
printf("Pong started\n");
while(1){
sem_wait(&pingsem);
printf("pong\n");
sleep(1);
sem_post(&pingsem);
}
}
int main(){
sem_destroy(&pingsem); //make sure the semaphore starts dead
sem_init(&pingsem, 0, 1); //initialize semaphore
pthread_t ping_thread, pong_thread; //start the threading
pthread_create(&ping_thread, NULL, ping, NULL);
pthread_create(&pong_thread, NULL, pong, NULL);
pthread_join(ping_thread,NULL);
pthread_join(pong_thread,NULL);
return 0;
}
I compile using:
gcc stest.c -o stest -lpthread -lrt
with no errors or warnings, but when I run it I get:
$ ./stest
Ping started
ping
ping
ping
ping
Pong started
ping
ping
.
. hundreds of pings
.
ping
ping
ping
pong
pong
pong
pong
.
. hundreds of pongs
.
It will eventually switch off but why are the threads not alternating printing every other one?
The problem shown in your example is, it's a race because neither read effectively blocks the other. Both threads run as the scheduler allows. The way it's coded, each thread can free-run (loop) multiple times during its time slice, and satisfies its own semaphore test. On a multi-core/multi-CPU system with a typical schedule, both threads can both run simultaneously and step all over each other somewhat arbitrarily.
Here's a working ping-ponging threads example that uses complimentary semaphores to create the ping-pong interlock you want.
#include <semaphore.h>
#include <pthread.h>
#include <stdio.h>
sem_t pingsem, pongsem;
void *
ping(void *arg)
{
for (;;) {
sem_wait(&pingsem);
printf("ping\n");
sem_post(&pongsem);
}
}
void *
pong(void *arg)
{
for (;;) {
sem_wait(&pongsem);
printf("pong\n");
sem_post(&pingsem);
}
}
int
main(void)
{
sem_init(&pingsem, 0, 0);
sem_init(&pongsem, 0, 1);
pthread_t ping_thread, pong_thread;
pthread_create(&ping_thread, NULL, ping, NULL);
pthread_create(&pong_thread, NULL, pong, NULL);
pthread_join(ping_thread, NULL);
pthread_join(pong_thread, NULL);
return 0;
}
Because when you create a thread it will execute as soon as the OS says it can!
So you created two threads like so:
pthread_create(&ping_thread, NULL, ping, NULL);
// scheduler interrupt from OS
pthread_create(&pong_thread, NULL, pong, NULL);
Which was fine, but the OS saw the first new thread and ran it until its timeslice was exhausted. Only then did the main thread get back control long enough to create the next thread.
As for why they're not alternating is a different issue! You see how difficult thread synchronization can be? You have this code:
while(1){
sem_wait(&pingsem);
printf("ping\n");
sem_post(&pingsem);
}
But you initialized the semaphore to the value of 1. So sem_wait decrements to 0, then prints a message, then increments back to 1. No problem, right?
Well the delay between the sem_post and the subsequent(next loop) sem_wait is only 1 instruction, a jump back to the beginning of the loop. So unless, by chance, the OS interrupts the thread after the sem_post, but before the sem_wait, the single thread will continue printing on its own.
You need two semaphores, 'pingsem' and 'pongsem', say. Initialize one to 1 and the other to zero. Then:
ping_thread:
while(true){
wait(pingsem);
doWork();
send(pongsem);
}
pong_thread:
while(true){
wait(pongsem);
doWork();
send(pingsem);
}
The one unit that was initialized into one semaphore then acts as a work token and is signaled back-and-forth between the threads. Only the thread with the token can do the work, the other has to wait until it gets the token.
James T. Smith has the right answer.. that since you didn't schedule out before grabbing your lock again, you would expect just about every time it would be able to re-grab the lock before the thread finished it's time slice.
If you want to force scheduling out so that the other one can run, you can try sleep(0) or sched_yield(). This will force a scheduling out so that if another thread was waiting to run it would. This would be more likely to see your ping,pong,ping,pong. But still not a guarantee and completely dependent on your OS scheduler (and probably only works on a single core system with both threads at the same priority).
Try this: (like I said.. no guarantees.. but a good possibility it will work)
void ping(){
printf("Ping started\n");
while(1){
sem_wait(&pingsem);
printf("ping\n");
sem_post(&pingsem);
sched_yield(); // Schedule out.
}
}
void pong(){
printf("Pong started\n");
while(1){
sem_wait(&pingsem);
printf("pong\n");
sleep(1);
sem_post(&pingsem);
sched_yield(); // Schedule out.
}
}
edit: changed to sched_yield()
The other answers are correct, I'm just posting code that will run as you desire (on OSX 10.10.3 anyway)
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
sem_t pingsem;
void ping(){
printf("Ping started\n");
while (1) {
sem_wait(&pingsem);
printf("ping\n");
sem_post(&pingsem);
}
}
void pong(){
printf("Pong started\n");
while (1) {
sem_wait(&pingsem);
printf("pong\n");
sem_post(&pingsem);
}
}
int main(){
sem_destroy(&pingsem); //make sure the semaphore starts dead
sem_init(&pingsem, 0, 1); //initialize semaphore
pthread_t ping_thread, pong_thread; //start the threading
pthread_create(&ping_thread, NULL, ping, (void *)0);
pthread_create(&pong_thread, NULL, pong, (void *)1);
pthread_exit(NULL);
return 0;
}

How to kill remaining threads when we come out of any single one? [duplicate]

This question already has answers here:
How can I kill a pthread that is in an infinite loop, from outside that loop?
(2 answers)
Closed 8 years ago.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define NUM_THREADS 5
void *PrintHello(void *threadid)
{
long tid;
tid = (long)threadid;
printf("Hello World! It's me, thread #%ld!\n", tid);
pthread_exit(NULL);
}
int main (int argc, char *argv[])//main
{
int rc;
long t;
for(t=0; t<NUM_THREADS; t++){
pthread_mutex_lock(&lock);
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);//creating thread
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
/* Last thing that main() should do */
pthread_exit(NULL);
}
how to kill remaining all threads when one is release
It is bad design to kill another thread. Standard design is to use a variable to indicate to the thread that it should finish. Each thread should check the variable at suitable points in the code and exit accordingly.
The reason is that only the thread knows when it is a good time to exit and it then can clean up after it self.
If you aren't bothered about bad design of your code I suggest you try pthread_cancel(thread[t]) to cancel the required thread. (refer http://man7.org/linux/man-pages/man3/pthread_cancel.3.html). I think this is a safe way to do it. Ensure you set the cancel state of your thread.
There's another way in which signals can be raised using pthread_kill(thread[t],SIGKILL) (refer: http://man7.org/linux/man-pages/man3/pthread_kill.3.html). This signal SIGKILL will kill your entire process. You can also raise some other signal instead of SIGKILL in case you want to kill selective thread (refer- https://en.wikipedia.org/wiki/Unix_signal#POSIX_signals) in this case you have to use a signal-handler in the thread (refer-[sigaction][1] or [signal][2]) to handle the signal you are trying to raise and handle it appropriately. But note this method is rather complicated as you will have to block signals in threads you don't want to kill.
Implement a two lock solution.
Psuedo code:
void *PrintHello() {
wait_for(lock1);
if( test_and_set(lock2) == true) {
release_others();
/* Do my stuffstuff... */
} else {
/* I'm not first. Exit. */
pthread_exit(null);
}
}

The version of pthread_join() that does not block main(): POSIX

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

thread termination issue (c programming)

I'm working on an application for Linux in C which uses multiple threads. The threads which are spawned by the main function do most of the work, and therefore usually finish last. I'm seeing some strange behavior, and I believe it's due to the main thread terminating before the spawned threads have a chance to finish their jobs. Here's some sample code to illustrate what I'm talking about:
#define _POSIX_C_SOURCE 200112L
#define _ISOC99_SOURCE
#define __EXTENSIONS__
#define _GNU_SOURCE
#include <pthread.h>
#include <stdio.h>
void
my_cleanup(void *arg)
{
printf("cleanup: %s\n", (char *)arg);
}
void *
thread_stuff(void *arg)
{
printf("thread started\n");
pthread_cleanup_push(cleanup, "running");
if (arg)
pthread_exit((void *)2);
pthread_cleanup_pop(0);
pthread_exit((void *)2);
}
int
main()
{
int err;
pthread_t tid1, tid2;
err = pthread_create(&tid1, NULL, thread_stuff, (void *)1);
err = pthread_create(&tid2, NULL, thread_stuff, (void *)1);
sleep(10); /* change the value here if you want */
return SUCCESS;
}
When this code is run, the message from the cleanup function is printed twice, as it should be, but other times when it is run, I see the message printed only once sometimes, and other times I see it printed three times or not at all. You add in the sleep function in the main function to play with how long it takes the main function to terminate.
What can I do to make the program run as it should? I suspect it has something to do with joining to the children, but I don't entirely understand the concept of a join or how to apply it to this situation.
Thanks in advance!
Yes, you should "join" the threads. "Joining" a thread simply means waiting until the thread has terminated. In other words, you would do
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
to wait until both threads have terminated.
Edit: What to do if you have a child thread which, in turn, creates a "grandchild" thread? As a rule, whoever created the thread should wait for it to terminate ("join" it). So in this scenario, the child thread would call phtread_join on the grandchild thread, and the main thread would call join on the child thread.
I think you want to run pthread_join on each of the threads when your main thread completes -- this makes the main thread stop until the given thread finishes running. Other threads can still complete first though, so running pthread_join on every thread will prevent the main thread from terminiating until all of the others have terminated.
There is a definite problem if main() finishes before the threads it spawned if you don't call pthread_exit() explicitly. All of the threads it created will terminate because main() is done and no longer exists to support the threads.
By having main() explicitly call pthread_exit() as the last thing it does, main() will block and be kept alive to support the threads it created until they are done.
int main()
{
int err;
pthread_t tid1, tid2;
err = pthread_create(&tid1, NULL, thread_stuff, (void *)1);
err = pthread_create(&tid2, NULL, thread_stuff, (void *)1);
sleep(10); /* change the value here if you want */
/* Add the pthread_exit */
pthread_exit(NULL);
return SUCCESS;
}
Refer for more info here

Resources