Is there an invalid pthread_t id?

LinuxPthreads

Linux Problem Overview


I would like to call pthread_join for a given thread id, but only if that thread has been started. The safe solution might be to add a variable to track which thread where started or not. However, I wonder if checking pthread_t variables is possible, something like the following code.

pthread_t thr1 = some_invalid_value; //0 ?
pthread_t thr2 = some_invalid_value;

/* thread 1 and 2 are strated or not depending on various condition */
....

/* cleanup */
if(thr1 != some_invalid_value)
    pthread_join(&thr1);

if(thr2 != some_invalid_value)
    pthread_join(&thr2);

Where some_invalid_value could be 0, or an implementation dependant 'PTHREAD_INVALID_ID' macro

PS : My assumption is that pthread_t types are comparable and assignable, assumption based on

PPS : I wanted to do this, because I thought calling pthread_join on invalid thread id was undefinde behaviour. It is not. However, joining a previously joined thread IS undefined behaviour. Now let's assume the above "function" is called repeatedly. Unconditionnally calling pthread_join and checking the result might result in calling pthread_join on a previously joined thread.

Linux Solutions


Solution 1 - Linux

Your assumption is incorrect to start with. pthread_t objects are opaque. You cannot compare pthread_t types directly in C. You should use pthread_equal instead.

Another consideration is that if pthread_create fails, the contents of your pthread_t will be undefined. It may not be set to your invalid value any more.

My preference is to keep the return values of the pthread_create calls (along with the thread IDs) and use that to determine whether each thread was started correctly.

Solution 2 - Linux

As suggested by Tony, you can use pthread_self() in this situation.

But do not compare thread_ts using == or !=. Use pthread_equal.

From the pthread_self man page:

> Therefore, variables of type pthread_t can't portably be compared using the C equality operator (==); use pthread_equal(3) instead.

Solution 3 - Linux

I recently ran into this same issue. If pthread_create() failed, I ended up with a undefined, invalid value stored in my phtread_t structure. As a result, I keep a boolean associated with each thread that gets set to true if pthread_create() succeeded.

Then all I need to do is:

void* status;
if (my_thread_running) {
  pthread_join(thread, &status);
  my_thread_running = false;
}

Solution 4 - Linux

Unfortunately, on systems where pthread_t is a pointer, pthread_equal() can return equality even though the two args refer to different threads, e.g. a thread can exit and a new thread can be created with the same pthread_t pointer value.

Solution 5 - Linux

This is an excellent question that I really wish would get more discussion in C++ classes and code tests.

One option for some systems-- which may seem like overkill to you, but has come in handy for me-- is to start a thread which does nothing other than efficiently wait for a tear-down signal, then quit. This thread stays running for the life of the application, going down very late in the shutdown sequence. Until that point, the ID of this thread can effectively be used as an "invalid thread" value-- or, more likely, as an "uninitialized" sentinel-- for most purposes. For example, my debug libraries typically track the threads from which mutexes were locked. This requires initialization of that tracking value to something sensible. Because POSIX rather stupidly declined to require that platforms define an INVALID_THREAD_ID, and because my libraries allow main() to lock things (making the pthread_self checks that are a good solution pthread_create unusable for lock tracking), this is the solution I have come to use. It works on any platform.

Note, however, that you have a little more design work to do if you want this to be able to initialize static thread references to invalid values.

Solution 6 - Linux

I was porting some code that used pthreads into a C++ application, and I had the same question. I decided it was easier to switch to the C++ std::thread object, which has the .joinable() method to decide whether or not to join, i.e.

 if (t.joinable()) t.join();

I found that just calling pthead_join on a bad pthread_t value (as a result of pthread_create failing) caused a seg fault, not just an error return value.

Solution 7 - Linux

Our issue was that we couldn't know if a pthread had been started or not, so we make it a pointer and allocate/de-allocate it and set it to NULL when not in use:

To start:

pthread_t *pth = NULL;

pth = malloc(sizeof(pthread_t));
int ret = pthread_create(pth, NULL, mythread, NULL);
if( ret != 0 )
{
    free(pth);
    pth = NULL;
}
    

And later when we need to join, whether or not the thread was started:

if (pth != NULL)
{
	pthread_join(*pth, NULL);
	free(pth);
	pth = NULL;
}

If you need to respawn threads quickly then the malloc/free cycle is undesirable, but it works for simple cases like ours.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionshodanexView Question on Stackoverflow
Solution 1 - Linuxqbert220View Answer on Stackoverflow
Solution 2 - LinuxMatView Answer on Stackoverflow
Solution 3 - LinuxIt'sPeteView Answer on Stackoverflow
Solution 4 - LinuxHavePoopWillStepView Answer on Stackoverflow
Solution 5 - LinuxbreakpointView Answer on Stackoverflow
Solution 6 - LinuxMark LakataView Answer on Stackoverflow
Solution 7 - LinuxKJ7LNWView Answer on Stackoverflow