By Trevor Boyd Smith


2010-01-28 17:01:58 8 Comments

In my destructor I want to destroy a thread cleanly.

My goal is to wait for a thread to finish executing and THEN destroy the thread.

The only thing I found about querying the state of a pthread is pthread_attr_setdetachstate but this only tells you if your thread is:

  • PTHREAD_CREATE_DETACHED
  • PTHREAD_CREATE_JOINABLE

Both of those have nothing to do with whether the thread is still running or not.

How do you query a pthread to see if it is still running?

7 comments

@Eric Buell 2019-03-01 01:39:19

I believe I've come up with a solution that at least works for Linux. Whenever I create a thread I have it save it's LWP (Light Weight Process ID) and assign it a unique name, eg. int lwp = syscall(SYS_gettid); prctl(PR_SET_NAME, (long)"unique name", 0, 0, 0);

Then, to check if the thread exists later I open /proc/pid/task/lwp/comm and read it. If the file exists and it's contents match the unique name I assigned, the thread exists. Note that this does NOT pass a possibly defunct/reused TID to any library function, so no crashes.

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <pthread.h>
#include <sys/prctl.h>
#include <sys/file.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <syscall.h>

pthread_t subthread_tid;
int       subthread_lwp;

#define UNIQUE_NAME "unique name"

bool thread_exists (pthread_t thread_id)
{
    char path[100];
    char thread_name[16];
    FILE *fp;
    bool  thread_exists = false;

    // If the /proc/<pid>/task/<lwp>/comm file exists and it's contents match the "unique name" the
    // thread exists, and it's the original thread (TID has NOT been reused).

    sprintf(path, "/proc/%d/task/%d/comm", getpid(), subthread_lwp);

    fp = fopen(path, "r");

    if( fp != NULL ) {

        fgets(thread_name, 16, fp);
        fclose(fp);

        // Need to trim off the newline
        thread_name[strlen(thread_name)-1] = '\0';

        if( strcmp(UNIQUE_NAME, thread_name) == 0 ) {
            thread_exists = true;
        }
    }

    if( thread_exists ) {
        printf("thread exists\n");
    } else {
        printf("thread does NOT exist\n");
    }

    return thread_exists;
}


void *subthread (void *unused)
{
    subthread_lwp = syscall(SYS_gettid);
    prctl(PR_SET_NAME, (long)UNIQUE_NAME, 0, 0, 0);

    sleep(10000);

    return NULL;
}


int main (int argc, char *argv[], char *envp[])
{
    int error_number;

    pthread_create(&subthread_tid, NULL, subthread, NULL);
    printf("pthread_create()\n");
    sleep(1);
    thread_exists(subthread_tid);

    pthread_cancel(subthread_tid);
    printf("pthread_cancel()\n");
    sleep(1);
    thread_exists(subthread_tid);

    error_number = pthread_join(subthread_tid, NULL);
    if( error_number == 0 ) {
        printf("pthread_join() successful\n");
    } else {
        printf("pthread_join() failed, %d\n", error_number);
    }
    thread_exists(subthread_tid);

    exit(0);
}

@pthread_kill 2012-03-26 10:44:22

pthread_kill(tid, 0);

No signal is sent, but error checking is still performed so you can use that to check existence of tid.

CAUTION: This answer is incorrect. The standard specifically prohibits passing the ID of a thread whose lifetime has ended. That ID might now specify a different thread or, worse, it might refer to memory that has been freed, causing a crash.

@leetNightshade 2012-10-26 15:21:05

For my problem, this was exactly what I needed to solve it, thanks. I used (pthread_kill(tid, 0) != ESRCH).

@Qiu Yangfan 2015-06-13 14:12:39

@Dev-iL 2017-03-20 21:43:37

@DavidSchwartz In such cases it is be better to mark your edit clearly as something that is not part of the original answer, as suggested here.

@Erik Alapää 2019-03-27 08:47:51

Additional comment on David Schwartz (correct) edit - the manpage (Linux) says this: 'POSIX.1-2008 recommends that if an implementation detects the use of a thread ID after the end of its lifetime, pthread_kill() should return the error ESRCH. The glibc implementation returns this error in the cases where an invalid thread ID can be detected. But note also that POSIX says that an attempt to use a thread ID whose lifetime has ended produces undefined behavior, and an attempt to use an invalid thread ID in a call to pthread_kill() can, for example, cause a segmentation fault.'

@newhouse 2016-09-26 11:20:55

Let me note on the "winning" answer, which has a huge hidden flaw, and in some contexts it can lead to crashes. Unless you use pthread_join, it will coming up again and again. Assume you are having a process and a shared library. Call the library lib.so.

  1. You dlopen it, you start a thread in it. Assume you don't want it join to it, so you set it detachable.
  2. Process and shared lib's logic doing its work, etc...
  3. You want to load out lib.so, because you don't need it any more.
  4. You call a shutdown on the thread and you say, that you want to read a flag afterwards from your lib.so's thread, that it have finished.
  5. You continue on another thread with dlclose, because you see, that you have saw, that the flag is now showing the thread as "finished"
  6. dlclose will load out all stack and code related memory.
  7. Whops, but dlclose does not stop threads. And you know, even when you are in the last line of the cleanup handler to set the "thread is finished" volatile atomic flag variable, you still have to return from a lot of methods on the stack, giving back values, etc. If a huge thread priority was given to #5+#6's thread, you will receive dlclose before you could REALLY stop on the thread. You will have some nice crashes sometimes.

Let me point out, that this is not a hipothetical problem, I had the same issue on our project.

@Priyesh Shah Pilu 2015-10-23 23:22:45

#include <string.h>
#include <stdio.h>
#include <pthread.h>
#include <signal.h>
#include <unistd.h>

void* thread1 (void* arg);
void* thread2 (void* arg);

int main()
{
    pthread_t thr_id;

    pthread_create(&thr_id, NULL, thread1, NULL);

    sleep(10);
}

void* thread1 (void* arg)
{
    pthread_t thr_id = 0;

    pthread_create(&thr_id, NULL, thread2, NULL);

    sleep(5);
    int ret = 0;
    if( (ret = pthread_kill(thr_id, 0)) == 0)
    {
        printf("still running\n");
        pthread_join(thr_id, NULL);
    }
    else
    {
        printf("RIP Thread = %d\n",ret);
    }
}

void* thread2 (void* arg)
{
//  sleep(5);
    printf("I am done\n");
}

@JAL 2015-10-23 23:51:24

While this code may answer the question, providing additional context regarding why and/or how this code answers the question improves its long-term value.

@Volomike 2016-04-01 07:32:35

You might not be aware, but doing a pthread_kill on a dead thread could potentially crash your application or cause unexpected results like deallocating memory used on something else. stackoverflow.com/a/1693235/105539

@jeremytrimble 2010-01-28 17:39:20

It sounds like you have two questions here:

How can I wait until my thread completes?

Answer: This is directly supported by pthreads -- make your thread-to-be-stopped JOINABLE (when it is first started), and use pthread_join() to block your current thread until the thread-to-be-stopped is no longer running.


How can I tell if my thread is still running?

Answer: You can add a "thread_complete" flag to do the trick:

Scenario: Thread A wants to know if Thread B is still alive.

When Thread B is created, it is given a pointer to the "thread_complete" flag address. The "thread_complete" flag should be initialized to NOT_COMPLETED before the thread is created. Thread B's entry point function should immediately call pthread_cleanup_push() to push a "cleanup handler" which sets the "thread_complete" flag to COMPLETED.

See details about cleanup handlers here: pthread cleanup handlers

You'll want to include a corresponding pthread_cleanup_pop(1) call to ensure that the cleanup handler gets called no matter what (i.e. if the thread exits normally OR due to cancellation, etc.).

Then, Thread A can simply check the "thread_complete" flag to see if Thread B has exited yet.

NOTE: Your "thread_complete" flag should be declared "volatile" and should be an atomic type -- the GNU compilers provide the sig_atomic_t for this purpose. This allows the two threads consistent access the same data without the need for synchronization constructs (mutexes/semaphores).

@R.. GitHub STOP HELPING ICE 2011-01-13 01:09:31

The cleanup handlers are entirely unnecessary unless you will be using cancellation (which is generally a rather dangerous tool). Also, you might want to use a pthread condition variable along with the flag variable to enable waiting on it without spinning and burning cpu cycles.

@Emil 2015-09-29 05:28:34

If the goal is to know whether or not to call join to "destroy" a pthread_t handle, checking a flag won't work because the thread might not have terminated when you check the flag but still manage to terminate before it is joined (note that joining a thread that has been joined results in undefined behavior, and leaving a joinable thread unjoined results in a leak.)

@newhouse 2016-09-26 11:25:46

To all, whom want to use the aforementioned solution, I have replied below with a problem with this solution. Read it before you apply into your solution. It might not be a problem in lots of cases, but you might want to know about it.

@David Schwartz 2016-09-26 11:30:02

@Emil There's no issue. Just make sure to call join once and only once. The race is harmless -- yes, your join might block for a tiny fraction of a second if you happen to check the flag after it's set and before the thread terminates, but the thread is about to terminate anyway.

@a3f 2019-05-04 15:26:53

In cases where you compute something and then signal thread_complete, so the computation result can be used, this is wrong. volatile sig_atomic_t can still be reordered, so it might be written before the computation result becomes visible and consumers can see an invalid state.

@Jeremy Friesner 2010-01-28 17:32:35

I think all you really need is to call pthread_join(). That call won't return until the thread has exited.

If you only want to poll to see whether the thread is still running or not (and note that is usually not what you should be wanting to do!), you could have the thread set a volatile boolean to false just before it exits... then your main-thread could read the boolean and if it's still true, you know the thread is still running. (if it's false, on the other hand, you know the thread is at least almost gone; it may still be running cleanup code that occurs after it sets the boolean to false, though, so even in this case you should still call pthread_join before trying to free any resources the thread might have access to)

@R.. GitHub STOP HELPING ICE 2011-01-13 01:10:16

+1 for explaining the potential race condition involved and a simple solution to it.

@user470379 2011-01-13 21:14:15

"then your main-thread could read the boolean and if it's still true, you know the thread is still running." -- In this case, you would only know if the thread has cleanly exited or not, which is not the same as still running or not.

@Jeremy Friesner 2013-02-03 04:30:12

Hmm, I'm probably missing a possibility here, but AFAICT the thread is either still running, or it has exited, or it has crashed. And if the thread has crashed, it's taken the rest of the process with it, so there is no second thread still around to detect that anyway.

@Dewfy 2010-01-28 17:13:30

There is not fully portable solution, look if your platform supports pthread_tryjoin_np or pthread_timedjoin_np. So you just check if thread can be joined (of course created with PTHREAD_CREATE_JOINABLE).

@R.. GitHub STOP HELPING ICE 2011-01-13 01:11:34

These interfaces were rejected by POSIX, and should not be used in applications intending to be portable. The same thing can be accomplished portably with a condition variable.

@Hubert Kario 2012-01-09 20:40:03

Just because the same thing can be accomplished with a condition variable doesn't mean that the pthread_tryjoin_np isn't a cleaner interface.

Related Questions

Sponsored Content

28 Answered Questions

[SOLVED] How do you set, clear, and toggle a single bit?

10 Answered Questions

[SOLVED] Improve INSERT-per-second performance of SQLite

6 Answered Questions

[SOLVED] What happens to a detached thread when main() exits?

2 Answered Questions

[SOLVED] Why is a while loop needed around pthread wait conditions?

17 Answered Questions

[SOLVED] How to timeout a thread

2 Answered Questions

2 Answered Questions

[SOLVED] C : how pthread dataspecific works?

  • 2009-02-14 10:58:25
  • claf
  • 2416 View
  • 4 Score
  • 2 Answer
  • Tags:   c pthreads

2 Answered Questions

[SOLVED] How to Kill a waiting pthread

Sponsored Content