I am getting back into using pthreads and the definition of pthread_join bothers me.
It says
"The pthread_join() function shall suspend execution of the calling
thread until the target thread terminates, unless the target thread
has already terminated. On return from a successful pthread_join()
call with a non-NULL value_ptr argument, the value passed to
pthread_exit() by the terminating thread shall be made available in
the location referenced by value_ptr. When a pthread_join() returns
successfully, the target thread has been terminated. The results of
multiple simultaneous calls to pthread_join() specifying the same
target thread are undefined. If the thread calling pthread_join() is
canceled, then the target thread shall not be detached."
I am trying to understand how, if I call pthread_join for one thread, then call pthread_join to start a second thread, the two threads are started, even though I imagine, the second pthread_join cannot be called because the first join has suspended the main thread from executing, and running the next line until pthread_exit is called from within the thread joined.
In particular, I imagine, the first pthread_join must wait until the specified thread has called pthread_exit, only then it should continue. However this is not the case, as I can do:
#include <pthread.h>
#include <stdio.h>
int avail = 0;
void *consumer(void *unused)
{
while (1) {
if (avail > 0) {
--avail;
puts("consumed");
}
}
}
void *producer(void *unused)
{
while (1) {
++avail;
puts("produced");
}
}
int main(int argc, char **argv)
{
pthread_t c_thread;
pthread_t p_thread;
pthread_create(&c_thread, 0, consumer, 0);
pthread_create(&p_thread, 0, producer, 0);
pthread_join(c_thread, 0);
pthread_join(p_thread, 0);
return 0;
}
ignoring the problem of possible race conditions to try to reduce code size, why are both the threads working, despite the first join suspending the main thread (thus, preventing the next join from being called, in my mind).
I would really like to understand how this works.
Thanks ahead of time.
Threads run concurrently, starting sometime during or after the call to pthread_create. Calling pthread_join has nothing to do with starting or running the thread, it simply waits until it exits. Both your threads have already been running and are still runnable at the point you enter and block on the first join and they will continue to run. The only thing blocked by the first join is your main thread.
The threads do not start in pthread_join, but rather in pthread_create. I mislead myself into thinking pthread_join was used to actually start the thread, whereas it is a non-busy wait for the specific thread to return before the main thread continues it's execution, in my case, main returns before the threads get a chance to call the puts function.
The second pthread_join in my code is never actually called, because main is indeed suspended from the first pthread_join waiting on c_thread to return. The second join in this particular scenario is a "no operation" and the program never actually gets to it because consumer never actually returns.
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/
According to the manual page:
The pthread_join() function shall suspend execution of the calling
thread until the target thread terminates, unless the target thread
has already terminated.
So, as I understand, the calling process will block until the specified thread exit.
Now consider the following code:
pthread_t thrs[NUMTHREADS];
for (int i = 0; i < NUMTHREADS; i++)
{
pthread_create(&thrs[i], NULL, thread_main, NULL);
}
pthread_join(thrs[0], NULL); /* will be blocked here */
pthread_join(thrs[1], NULL);
pthread_join(thrs[2], NULL);
/* ... */
pthread_join(thrs[NUMTHREADS - 1], NULL);
The calling thread will be blocked in the call to pthread_join(thrs[0], NULL), until thrs[0] exit in some way. But how if another thread, for example, thrs[2] call pthread_exit() while we are blocked in the call to pthread_join(thrs[0], NULL)? Do we have to wait for thrs[0] to exit in order to receive the return value of thrs[2]?
But how if another thread, say thrs[2] exit while we are blocked in
the call to pthread_join(thrs[0], NULL)?
Yes, it could happen. In that case, pthread_join(thrs[2], NULL); will return immediately.
Do we have to wait for thrs[0] to exit in order to receive the return
value of thrs[2]?
Yes, you have to wait for thr[0] to terminate.
(Not directly related to the question)
It's not necessary to call pthread_join() on every thread you create. It's a convenient function to get the return status from thread(s). If you don't need to know the termination status of the thread, you could
create the thread by seeting the "detached" attribute or call pthread_detach(pthread_self()); from the thread itself to make it detached.
In some cases, you would want the threads created to continue execution but no longer need the main thread. In that case, you could call pthread_exit(NULL); from main thread which will let other threads to continue even after main thread exits.
Yes - the main thread blocked on thrs[0] will not get the result from thrs[2] until after thrs[[0] and thrs[1] have also exited.
If you need more flexibility one option is to do something like having the threads post their results in a queue or signal in some other way that the thread needs to be joined. The main thread can monitor that queue/signal and get the necessary results (which could come from a pthread_join() that is done on the thread that is known to be completed from information int he queue/signal).
Yes. The code is executed in serial.
I cant terminate the thread, it keeps sending things even after I close the terminal...
void *RTPfun(void * client_addr);
int main(int argc, char *argv[])
{
pthread_t RTPthread;
pthread_create(&RTPthread, NULL, &RTPfun, (void*)client_addr);
...
...
pthread_exit(&RTPfun);
return 0;
}
void *RTPfun(void * client_addr)
{
...
...
return 0;
}
Can someone tell me what am I doing wrong?
Thanks!
pthread_exit kills your current thread.
Notice, that if you kill the main thread as you do, it does not terminate the process. Other threads keep running.
You probably want to use pthread_cancel.
More generally though, killing threads is a bad idea. Correct way is to ask your threads politely to terminate and wait till they do.
If you call exit() from main, it will terminate main thread with all other thread.
If you call the method pthread_exit() from your main it will terminate main thread and let other thread will run continuously.
In your case you are calling pthread_exit() from main so your main thread get terminated, and other thread running until thread gets finish the job.
To cancel thread Add Below in RTPfun and add pthread_cancel in main.
/* call this when you are not ready to cancel the thread */
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
/* call this when you are ready to cancel the thread */
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
Working sample code:
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
void *RTPfun(void * client_addr);
int main(int argc, char *argv[])
{
pthread_t RTPthread;
int client_addr;
pthread_create(&RTPthread, NULL, &RTPfun, (void*)client_addr);
sleep(2);
pthread_cancel(RTPthread);
pthread_join(RTPthread, NULL);
return 0;
}
void *RTPfun(void * client_addr)
{
int count = 0;
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
while(1) {
if(count > 10) {
printf("thread set for cancel\n");
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
}
sleep(1);
printf("count:%d\n", count);
count ++;
}
return 0;
}
Used sleep in code for just understanding.
My understanding:
From "man pthread_exit" clearly talks about the description and rational behavior.
we will need to clean-up all respected resource that are been used in the thread created.
" The pthread_exit() function shall terminate the calling thread and make the value value_ptr available to any successful join with the terminating thread."
we shall pass "value_ptr" to exit(value_ptr) --> this will help to analyse what was the results of exit process.
obviously exit() - call exiting from the process, will release resources that used for.
In other way, you can create pthread in detached state, this attribute will reclaim the resources implicitly when pthread_exit . Refer "man pthread_detach".
We don't need to use pthread_join .. either go for pthread_detach again its simple go ahead set attribute .
/* set the thread detach state */
ret = pthread_attr_setdetachstate(&tattr,PTHREAD_CREATE_DETACHED);
Thanks.
Sankar
Your pthread_exit() exits the current thread. The parameter is used to pass a return value to any thread that then wants to join with it - and not to specify which thread to exit, as your code is implying.
The nicest way to do what you want is to use pthread_cancel() from your main thread. It takes the thread to cancel as a parameter, and then sends a cancellation request to that thread. Notice though, that by default cancellation is deferred, so your thread will keep on running until it hits a function that is a cancellation point - if you don't use any of those functions, you can insert an explicit cancellation point with a call to pthread_testcancel().
If you need to do some cleanup (for instance to free allocated memory, unlock mutexes, etc), you can insert a cleanup handler that is automatically called when canceling the thread. Have a look at pthread_cleanup_push() for this.
You can also set your thread to use asynchronous cancellation - your thread can then be canceled immediately, without hitting a cancellation point. However, asynchronous cancellation should only be used if you aren't using any system calls at all (that is, it's okay if you're purely doing calculations on already available data - but not if you're for instance using printf, file I/O, socket communication or similar), as otherwise you'll risk your system ending up in an inconsistent state.
After calling pthread_cancel(), your main thread should call pthread_join() on the canceled thread, to make sure all thread resources are cleaned up (unless you create the thread as detached).
You can of course also just have a shared doExit flag between the two threads, that the main thread can set, and which the other thread looks at from time to time. It's basically a manual way of using pthread_cancel().
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 create a thread and I put it into an infinite loop. I get memory leaks when checking the code with valgrind. Here is my code:
#include <pthread.h>
#include <time.h>
void thread_do(void){
while(1){}
}
int main(){
pthread_t th;
pthread_create(&th, NULL, (void *)thread_do, NULL);
sleep(2);
/* I want to kill thread here */
sleep(2);
return 0;
}
So a thread is created in main and just runs thread_do() all the time. Is there a way to kill it from inside main after 2 seconds? I have tried both pthread_detach(th) and pthread_cancel(th) but I still get leaks.
As #sarnold pointed out, by default your thread can't be cancelled with pthread_cancel() without calling any functions that are cancellation points... but this can be changed by using pthread_setcanceltype() to set the thread's cancellation type to asynchronous instead of deferred. To do that, you'd add something like pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL); near the start of your thread function, before you start the loop. You would then be able to terminate the thread by calling pthread_cancel(th) from main().
Note, though, that cancelling threads this way (whether asynchronous or not) doesn't clean up any resources allocated in the thread function (as noted by Kevin in a comment). In order to do this cleanly, you can:
Ensure that the thread doesn't do anything it needs to clean up before exit (e.g. using malloc() to allocate a buffer)
Ensure that you have some way of cleaning up after the thread elsewhere, after the thread exits
Use pthread_cleanup_push() and pthread_cleanup_pop() to add cleanup handlers to clean up resources when the thread is cancelled. Note that this is still risky if the cancellation type is asynchronous, because the thread could be cancelled between allocating a resource and adding the cleanup handler.
Avoid using pthread_cancel() and have the thread check some condition to determine when to terminate (which would be checked in long-running loops). Since your thread then checks for termination itself, it can do whatever cleanup it needs to after the check.
One way of implementing the last option is to use a mutex as a flag, and test it with pthread_mutex_trylock() wrapped in a function to use in the loop tests:
#include <pthread.h>
#include <unistd.h>
#include <errno.h>
/* Returns 1 (true) if the mutex is unlocked, which is the
* thread's signal to terminate.
*/
int needQuit(pthread_mutex_t *mtx)
{
switch(pthread_mutex_trylock(mtx)) {
case 0: /* if we got the lock, unlock and return 1 (true) */
pthread_mutex_unlock(mtx);
return 1;
case EBUSY: /* return 0 (false) if the mutex was locked */
return 0;
}
return 1;
}
/* Thread function, containing a loop that's infinite except that it checks for
* termination with needQuit()
*/
void *thread_do(void *arg)
{
pthread_mutex_t *mx = arg;
while( !needQuit(mx) ) {}
return NULL;
}
int main(int argc, char *argv[])
{
pthread_t th;
pthread_mutex_t mxq; /* mutex used as quit flag */
/* init and lock the mutex before creating the thread. As long as the
mutex stays locked, the thread should keep running. A pointer to the
mutex is passed as the argument to the thread function. */
pthread_mutex_init(&mxq,NULL);
pthread_mutex_lock(&mxq);
pthread_create(&th,NULL,thread_do,&mxq);
sleep(2);
/* unlock mxq to tell the thread to terminate, then join the thread */
pthread_mutex_unlock(&mxq);
pthread_join(th,NULL);
sleep(2);
return 0;
}
If the thread is not detached (it generally isn't by default), you should call pthread_join() after stopping the thread. If the thread is detached, you don't need to join it, but you won't know exactly when it terminates (or even approximately, unless you add another way to indicate its exit).
A few small thoughts:
You're trying to cancel your thread, but if the cancellation policy in place is for a deferred cancellation, your thread_do() will never be canceled, because it never calls any functions that are cancellation points:
A thread's cancellation type, determined by
pthread_setcanceltype(3), may be either asynchronous or
deferred (the default for new threads). Asynchronous
cancelability means that the thread can be canceled at any
time (usually immediately, but the system does not guarantee
this). Deferred cancelability means that cancellation will
be delayed until the thread next calls a function that is a
cancellation point. A list of functions that are or may be
cancellation points is provided in pthreads(7).
You're not joining the thread in your simple example code; call pthread_join(3) before the end of your program:
After a canceled thread has terminated, a join with that
thread using pthread_join(3) obtains PTHREAD_CANCELED as the
thread's exit status. (Joining with a thread is the only way
to know that cancellation has completed.)