Main Content

Use of undefined thread ID

Thread ID from failed thread creation used in subsequent thread functions

Description

This defect occurs when a thread creation function such as pthread_create fails but you continue to use the ID from the thread creation.

For instance, pthread_join uses an undefined thread ID after the previous thread creation failed. The nonzero return value from pthread_create indicates the failed thread creation.

pthread_t id;
if(0! = pthread_create(&id, attr, start_func, NULL)) {
    ...
    phread_join(id, NULL);
    ...
}
The issue is also flagged if you do not check the return value from a call to pthread_create.

Risk

According to the POSIX® standard, if thread creation fails, the contents of the thread ID are undefined. The use of an undefined thread ID can lead to unpredictable results.

The issue often indicates a programming error. For instance, it is possible that you tested for nonzero values to determine successful thread creation:

if(0 != pthread_create(&id, attr, start_func, NULL))
instead of zero:
if(0 == pthread_create(&id, attr, start_func, NULL))

Fix

If the use of an undefined thread ID comes from a programming error, fix the error. Otherwise, remove the thread functions that are using the undefined ID.

Examples

expand all

#include <stddef.h>
#include <pthread.h>
#define thread_success 0

extern void *thread_func(void *arg);


int main() {
    pthread_t id;
    if(thread_success != pthread_create(&id, NULL, thread_func, NULL)) {
         if(thread_success == pthread_join(id, NULL)) {
         }
    }

    return 0;
}

In this example, if pthread_create returns a nonzero value, thread creation has failed. The value of *id is undefined. The subsequent call to pthread_join uses this undefined value.

Correction – Join Threads After Successful Thread Creation

One possible correction is to call pthread_join with the thread ID as argument only if pthread_create returns zero.

#include <stddef.h>
#include <pthread.h>
#define thread_success 0

extern void *thread_func(void *arg);


int main() {
    pthread_t id;
    if(thread_success == pthread_create(&id, NULL, thread_func, NULL)) {
         if(thread_success == pthread_join(id, NULL)) {
         }
    }

    return 0;
}
#include <stddef.h>
#include <pthread.h>
#define thread_success 0

extern void *thread_func(void *arg);


int main() {
    pthread_t id;
    pthread_create(&id, NULL, thread_func, NULL); 
    if(thread_success == pthread_join(id, NULL)) {
    }

    return 0;
}

In this example, the return value of pthread_create is not checked. If thread creation fails, the error does not get handled. A possibly undefined thread ID is later used in the pthread_join function.

Correction – Handle Errors from Thread Creation

One possible correction is to use the ID from thread creation only if the return value from pthread_create indicates successful thread creation.

#include <stddef.h>
#include <pthread.h>
#define thread_success 0

extern void *thread_func(void *arg);


int main() {
    pthread_t id;
    if(thread_success == pthread_create(&id, NULL, thread_func, NULL)) {
         if(thread_success == pthread_join(id, NULL)) {
         }
    }

    return 0;
}

Result Information

Group: Concurrency
Language: C
Default: Off
Command-Line Syntax: UNDEFINED_THREAD_ID
Impact: Medium

Version History

Introduced in R2019b