Related
I am new to pthreads, and I am trying to understand it. I saw some examples like the following.
I could see that the main() is blocked by the API pthread_exit(), and I have seen examples where the main function is blocked by the API pthread_join(). I am not able to understand when to use what?
I am referring to the following site - https://computing.llnl.gov/tutorials/pthreads/. I am not able to get the concept of when to use pthread_join() and when to use pthread_exit().
Can somebody please explain? Also, a good tutorial link for pthreads will be appreciated.
#include <pthread.h>
#include <stdio.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[])
{
pthread_t threads[NUM_THREADS];
int rc;
long t;
for(t=0; t<NUM_THREADS; t++){
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
/* Last thing that main() should do */
pthread_exit(NULL);
Realized one more thing i.e.
pthread_cancel(thread);
pthread_join(thread, NULL);
Sometimes, you want to cancel the thread while it is executing.
You could do this using pthread_cancel(thread);.
However, remember that you need to enable pthread cancel support.
Also, a clean up code upon cancellation.
thread_cleanup_push(my_thread_cleanup_handler, resources);
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0);
static void my_thread_cleanup_handler(void *arg)
{
// free
// close, fclose
}
As explained in the openpub documentations,
pthread_exit() will exit the thread that calls it.
In your case since the main calls it, main thread will terminate whereas your spawned threads will continue to execute. This is mostly used in cases where the
main thread is only required to spawn threads and leave the threads to do their job
pthread_join
will suspend execution of the thread that has called it unless the target thread terminates
This is useful in cases when you want to wait for thread/s to terminate before further
processing in main thread.
pthread_exit terminates the calling thread while pthread_join suspends execution of calling thread until target threads completes execution.
They are pretty much well explained in detail in the open group documentation:
pthread_exit
pthread_join
Both methods ensure that your process doesn't end before all of your threads have ended.
The join method has your thread of the main function explicitly wait for all threads that are to be "joined".
The pthread_exit method terminates your main function and thread in a controlled way. main has the particularity that ending main otherwise would be terminating your whole process including all other threads.
For this to work, you have to be sure that none of your threads is using local variables that are declared inside them main function. The advantage of that method is that your main doesn't have to know all threads that have been started in your process, e.g because other threads have themselves created new threads that main doesn't know anything about.
The pthread_exit() API
as has been already remarked, is used for the calling thread termination.
After a call to that function a complicating clean up mechanism is started.
When it completes the thread is terminated.
The pthread_exit() API is also called implicitly when a call to the return() routine occurs in a thread created by pthread_create().
Actually, a call to return() and a call to pthread_exit() have the same impact, being called from a thread created by pthread_create().
It is very important to distinguish the initial thread, implicitly created when the main() function starts, and threads created by pthread_create().
A call to the return() routine from the main() function implicitly invokes the exit() system call and the entire process terminates.
No thread clean up mechanism is started.
A call to the pthread_exit() from the main() function causes the clean up mechanism to start and when it finishes its work the initial thread terminates.
What happens to the entire process (and to other threads) when pthread_exit() is called from the main() function depends on the PTHREAD implementation.
For example, on IBM OS/400 implementation the entire process is terminated, including other threads, when pthread_exit() is called from the main() function.
Other systems may behave differently.
On most modern Linux machines a call to pthread_exit() from the initial thread does not terminate the entire process until all threads termination.
Be careful using pthread_exit() from main(), if you want to write a portable application.
The pthread_join() API
is a convenient way to wait for a thread termination.
You may write your own function that waits for a thread termination, perhaps more suitable to your application, instead of using pthread_join().
For example, it can be a function based on waiting on conditional variables.
I would recommend for reading a book of David R. Butenhof “Programming with POSIX Threads”.
It explains the discussed topics (and more complicated things) very well (although some implementation details, such as pthread_exit usage in the main function, not always reflected in the book).
You don't need any calls to pthread_exit(3) in your particular code.
In general, the main thread should not call pthread_exit, but should often call pthread_join(3) to wait for some other thread to finish.
In your PrintHello function, you don't need to call pthread_exit because it is implicit after returning from it.
So your code should rather be:
void *PrintHello(void *threadid) {
long tid = (long)threadid;
printf("Hello World! It's me, thread #%ld!\n", tid);
return threadid;
}
int main (int argc, char *argv[]) {
pthread_t threads[NUM_THREADS];
int rc;
intptr_t t;
// create all the threads
for(t=0; t<NUM_THREADS; t++){
printf("In main: creating thread %ld\n", (long) t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
if (rc) { fprintf(stderr, "failed to create thread #%ld - %s\n",
(long)t, strerror(rc));
exit(EXIT_FAILURE);
};
}
pthread_yield(); // useful to give other threads more chance to run
// join all the threads
for(t=0; t<NUM_THREADS; t++){
printf("In main: joining thread #%ld\n", (long) t);
rc = pthread_join(&threads[t], NULL);
if (rc) { fprintf(stderr, "failed to join thread #%ld - %s\n",
(long)t, strerror(rc));
exit(EXIT_FAILURE);
}
}
}
pthread_exit() will terminate the calling thread and exit from that(but resources used by calling thread is not released to operating system if it is not detached from main thread.)
pthrade_join() will wait or block the calling thread until target thread is not terminated.
In simple word it will wait for to exit the target thread.
In your code, if you put sleep(or delay) in PrintHello function before pthread_exit(), then main thread may be exit and terminate full process, Although your PrintHello function is not completed it will terminate. If you use pthrade_join() function in main before calling pthread_exit() from main it will block main thread and wait to complete your calling thread (PrintHello).
Hmm.
POSIX pthread_exit description from http://pubs.opengroup.org/onlinepubs/009604599/functions/pthread_exit.html:
After a thread has terminated, the result of access to local (auto) variables of the thread is
undefined. Thus, references to local variables of the exiting thread should not be used for
the pthread_exit() value_ptr parameter value.
Which seems contrary to the idea that local main() thread variables will remain accessible.
Using pthread_exit in the main thread(in place of pthread_join), will leave the main thread in defunct(zombie) state. Since not using pthread_join, other joinable threads which are terminated will also remain in the zombie state and cause resource leakage.
Failure to join with a thread that is joinable (i.e., one that is
not detached), produces a "zombie thread". Avoid doing this, since
each zombie thread consumes some system resources, and when enough
zombie threads have accumulated, it will no longer be possible to
create new threads (or processes).
Another point is keeping the main thread in the defunct state, while other threads are running may cause implementation dependent issues in various conditions like if resources are allocated in main thread or variables which are local to the main thread are used in other threads.
Also, all the shared resources are released only when the process exits, it's not saving any resources. So, I think using pthread_exit in place of pthread_join should be avoided.
When pthread_exit() is called, the calling threads stack is no longer addressable as "active" memory for any other thread. The .data, .text and .bss parts of "static" memory allocations are still available to all other threads. Thus, if you need to pass some memory value into pthread_exit() for some other pthread_join() caller to see, it needs to be "available" for the thread calling pthread_join() to use. It should be allocated with malloc()/new, allocated on the pthread_join threads stack, 1) a stack value which the pthread_join caller passed to pthread_create or otherwise made available to the thread calling pthread_exit(), or 2) a static .bss allocated value.
It's vital to understand how memory is managed between a threads stack, and values store in .data/.bss memory sections which are used to store process wide values.
#include<stdio.h>
#include<pthread.h>
#include<semaphore.h>
sem_t st;
void *fun_t(void *arg);
void *fun_t(void *arg)
{
printf("Linux\n");
sem_post(&st);
//pthread_exit("Bye");
while(1);
pthread_exit("Bye");
}
int main()
{
pthread_t pt;
void *res_t;
if(pthread_create(&pt,NULL,fun_t,NULL) == -1)
perror("pthread_create");
if(sem_init(&st,0,0) != 0)
perror("sem_init");
if(sem_wait(&st) != 0)
perror("sem_wait");
printf("Sanoundry\n");
//Try commenting out join here.
if(pthread_join(pt,&res_t) == -1)
perror("pthread_join");
if(sem_destroy(&st) != 0)
perror("sem_destroy");
return 0;
}
Copy and paste this code on a gdb. Onlinegdb would work and see for yourself.
Make sure you understand once you have created a thread, the process run along with main together at the same time.
Without the join, main thread continue to run and return 0
With the join, main thread would be stuck in the while loop because it waits for the thread to be done executing.
With the join and delete the commented out pthread_exit, the thread will terminate before running the while loop and main would continue
Practical usage of pthread_exit can be used as an if conditions or case statements to ensure 1 version of some code runs before exiting.
void *fun_t(void *arg)
{
printf("Linux\n");
sem_post(&st);
if(2-1 == 1)
pthread_exit("Bye");
else
{
printf("We have a problem. Computer is bugged");
pthread_exit("Bye"); //This is redundant since the thread will exit at the end
//of scope. But there are instances where you have a bunch
//of else if here.
}
}
I would want to demonstrate how sometimes you would need to have a segment of code running first using semaphore in this example.
#include<stdio.h>
#include<pthread.h>
#include<semaphore.h>
sem_t st;
void* fun_t (void* arg)
{
printf("I'm thread\n");
sem_post(&st);
}
int main()
{
pthread_t pt;
pthread_create(&pt,NULL,fun_t,NULL);
sem_init(&st,0,0);
sem_wait(&st);
printf("before_thread\n");
pthread_join(pt,NULL);
printf("After_thread\n");
}
Noticed how fun_t is being ran after "before thread" The expected output if it is linear from top to bottom would be before thread, I'm thread, after thread. But under this circumstance, we block the main from running any further until the semaphore is released by func_t. The result can be verified with https://www.onlinegdb.com/
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 am new to pthreads, and I am trying to understand it. I saw some examples like the following.
I could see that the main() is blocked by the API pthread_exit(), and I have seen examples where the main function is blocked by the API pthread_join(). I am not able to understand when to use what?
I am referring to the following site - https://computing.llnl.gov/tutorials/pthreads/. I am not able to get the concept of when to use pthread_join() and when to use pthread_exit().
Can somebody please explain? Also, a good tutorial link for pthreads will be appreciated.
#include <pthread.h>
#include <stdio.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[])
{
pthread_t threads[NUM_THREADS];
int rc;
long t;
for(t=0; t<NUM_THREADS; t++){
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
/* Last thing that main() should do */
pthread_exit(NULL);
Realized one more thing i.e.
pthread_cancel(thread);
pthread_join(thread, NULL);
Sometimes, you want to cancel the thread while it is executing.
You could do this using pthread_cancel(thread);.
However, remember that you need to enable pthread cancel support.
Also, a clean up code upon cancellation.
thread_cleanup_push(my_thread_cleanup_handler, resources);
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0);
static void my_thread_cleanup_handler(void *arg)
{
// free
// close, fclose
}
As explained in the openpub documentations,
pthread_exit() will exit the thread that calls it.
In your case since the main calls it, main thread will terminate whereas your spawned threads will continue to execute. This is mostly used in cases where the
main thread is only required to spawn threads and leave the threads to do their job
pthread_join
will suspend execution of the thread that has called it unless the target thread terminates
This is useful in cases when you want to wait for thread/s to terminate before further
processing in main thread.
pthread_exit terminates the calling thread while pthread_join suspends execution of calling thread until target threads completes execution.
They are pretty much well explained in detail in the open group documentation:
pthread_exit
pthread_join
Both methods ensure that your process doesn't end before all of your threads have ended.
The join method has your thread of the main function explicitly wait for all threads that are to be "joined".
The pthread_exit method terminates your main function and thread in a controlled way. main has the particularity that ending main otherwise would be terminating your whole process including all other threads.
For this to work, you have to be sure that none of your threads is using local variables that are declared inside them main function. The advantage of that method is that your main doesn't have to know all threads that have been started in your process, e.g because other threads have themselves created new threads that main doesn't know anything about.
The pthread_exit() API
as has been already remarked, is used for the calling thread termination.
After a call to that function a complicating clean up mechanism is started.
When it completes the thread is terminated.
The pthread_exit() API is also called implicitly when a call to the return() routine occurs in a thread created by pthread_create().
Actually, a call to return() and a call to pthread_exit() have the same impact, being called from a thread created by pthread_create().
It is very important to distinguish the initial thread, implicitly created when the main() function starts, and threads created by pthread_create().
A call to the return() routine from the main() function implicitly invokes the exit() system call and the entire process terminates.
No thread clean up mechanism is started.
A call to the pthread_exit() from the main() function causes the clean up mechanism to start and when it finishes its work the initial thread terminates.
What happens to the entire process (and to other threads) when pthread_exit() is called from the main() function depends on the PTHREAD implementation.
For example, on IBM OS/400 implementation the entire process is terminated, including other threads, when pthread_exit() is called from the main() function.
Other systems may behave differently.
On most modern Linux machines a call to pthread_exit() from the initial thread does not terminate the entire process until all threads termination.
Be careful using pthread_exit() from main(), if you want to write a portable application.
The pthread_join() API
is a convenient way to wait for a thread termination.
You may write your own function that waits for a thread termination, perhaps more suitable to your application, instead of using pthread_join().
For example, it can be a function based on waiting on conditional variables.
I would recommend for reading a book of David R. Butenhof “Programming with POSIX Threads”.
It explains the discussed topics (and more complicated things) very well (although some implementation details, such as pthread_exit usage in the main function, not always reflected in the book).
You don't need any calls to pthread_exit(3) in your particular code.
In general, the main thread should not call pthread_exit, but should often call pthread_join(3) to wait for some other thread to finish.
In your PrintHello function, you don't need to call pthread_exit because it is implicit after returning from it.
So your code should rather be:
void *PrintHello(void *threadid) {
long tid = (long)threadid;
printf("Hello World! It's me, thread #%ld!\n", tid);
return threadid;
}
int main (int argc, char *argv[]) {
pthread_t threads[NUM_THREADS];
int rc;
intptr_t t;
// create all the threads
for(t=0; t<NUM_THREADS; t++){
printf("In main: creating thread %ld\n", (long) t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
if (rc) { fprintf(stderr, "failed to create thread #%ld - %s\n",
(long)t, strerror(rc));
exit(EXIT_FAILURE);
};
}
pthread_yield(); // useful to give other threads more chance to run
// join all the threads
for(t=0; t<NUM_THREADS; t++){
printf("In main: joining thread #%ld\n", (long) t);
rc = pthread_join(&threads[t], NULL);
if (rc) { fprintf(stderr, "failed to join thread #%ld - %s\n",
(long)t, strerror(rc));
exit(EXIT_FAILURE);
}
}
}
pthread_exit() will terminate the calling thread and exit from that(but resources used by calling thread is not released to operating system if it is not detached from main thread.)
pthrade_join() will wait or block the calling thread until target thread is not terminated.
In simple word it will wait for to exit the target thread.
In your code, if you put sleep(or delay) in PrintHello function before pthread_exit(), then main thread may be exit and terminate full process, Although your PrintHello function is not completed it will terminate. If you use pthrade_join() function in main before calling pthread_exit() from main it will block main thread and wait to complete your calling thread (PrintHello).
Hmm.
POSIX pthread_exit description from http://pubs.opengroup.org/onlinepubs/009604599/functions/pthread_exit.html:
After a thread has terminated, the result of access to local (auto) variables of the thread is
undefined. Thus, references to local variables of the exiting thread should not be used for
the pthread_exit() value_ptr parameter value.
Which seems contrary to the idea that local main() thread variables will remain accessible.
Using pthread_exit in the main thread(in place of pthread_join), will leave the main thread in defunct(zombie) state. Since not using pthread_join, other joinable threads which are terminated will also remain in the zombie state and cause resource leakage.
Failure to join with a thread that is joinable (i.e., one that is
not detached), produces a "zombie thread". Avoid doing this, since
each zombie thread consumes some system resources, and when enough
zombie threads have accumulated, it will no longer be possible to
create new threads (or processes).
Another point is keeping the main thread in the defunct state, while other threads are running may cause implementation dependent issues in various conditions like if resources are allocated in main thread or variables which are local to the main thread are used in other threads.
Also, all the shared resources are released only when the process exits, it's not saving any resources. So, I think using pthread_exit in place of pthread_join should be avoided.
When pthread_exit() is called, the calling threads stack is no longer addressable as "active" memory for any other thread. The .data, .text and .bss parts of "static" memory allocations are still available to all other threads. Thus, if you need to pass some memory value into pthread_exit() for some other pthread_join() caller to see, it needs to be "available" for the thread calling pthread_join() to use. It should be allocated with malloc()/new, allocated on the pthread_join threads stack, 1) a stack value which the pthread_join caller passed to pthread_create or otherwise made available to the thread calling pthread_exit(), or 2) a static .bss allocated value.
It's vital to understand how memory is managed between a threads stack, and values store in .data/.bss memory sections which are used to store process wide values.
#include<stdio.h>
#include<pthread.h>
#include<semaphore.h>
sem_t st;
void *fun_t(void *arg);
void *fun_t(void *arg)
{
printf("Linux\n");
sem_post(&st);
//pthread_exit("Bye");
while(1);
pthread_exit("Bye");
}
int main()
{
pthread_t pt;
void *res_t;
if(pthread_create(&pt,NULL,fun_t,NULL) == -1)
perror("pthread_create");
if(sem_init(&st,0,0) != 0)
perror("sem_init");
if(sem_wait(&st) != 0)
perror("sem_wait");
printf("Sanoundry\n");
//Try commenting out join here.
if(pthread_join(pt,&res_t) == -1)
perror("pthread_join");
if(sem_destroy(&st) != 0)
perror("sem_destroy");
return 0;
}
Copy and paste this code on a gdb. Onlinegdb would work and see for yourself.
Make sure you understand once you have created a thread, the process run along with main together at the same time.
Without the join, main thread continue to run and return 0
With the join, main thread would be stuck in the while loop because it waits for the thread to be done executing.
With the join and delete the commented out pthread_exit, the thread will terminate before running the while loop and main would continue
Practical usage of pthread_exit can be used as an if conditions or case statements to ensure 1 version of some code runs before exiting.
void *fun_t(void *arg)
{
printf("Linux\n");
sem_post(&st);
if(2-1 == 1)
pthread_exit("Bye");
else
{
printf("We have a problem. Computer is bugged");
pthread_exit("Bye"); //This is redundant since the thread will exit at the end
//of scope. But there are instances where you have a bunch
//of else if here.
}
}
I would want to demonstrate how sometimes you would need to have a segment of code running first using semaphore in this example.
#include<stdio.h>
#include<pthread.h>
#include<semaphore.h>
sem_t st;
void* fun_t (void* arg)
{
printf("I'm thread\n");
sem_post(&st);
}
int main()
{
pthread_t pt;
pthread_create(&pt,NULL,fun_t,NULL);
sem_init(&st,0,0);
sem_wait(&st);
printf("before_thread\n");
pthread_join(pt,NULL);
printf("After_thread\n");
}
Noticed how fun_t is being ran after "before thread" The expected output if it is linear from top to bottom would be before thread, I'm thread, after thread. But under this circumstance, we block the main from running any further until the semaphore is released by func_t. The result can be verified with https://www.onlinegdb.com/
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'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