Main Content

CERT C: Rule CON39-C

Do not join or detach a thread that was previously joined or detached

Description

This checker is deactivated in a default Polyspace® as You Code analysis. See Checkers Deactivated in Polyspace as You Code Analysis (Polyspace Access).

Rule Definition

Do not perform operations that can block while holding a lock.1

Polyspace Implementation

The rule checker checks for Join or detach of a joined or detached thread.

Examples

expand all

Issue

Join or detach of a joined or detached thread occurs when:

  • A thread that is joined was previously joined or detached

  • A thread that is detached was previously joined or detached.

The Result Details pane describes if the thread was previously joined or detached and also shows previous related events.

For instance, the issue occurs when a thread joined with thrd_join is then detached with pthread_detach:

thrd_t id;
//...
thrd_join(id, NULL);
thrd_detach(id);

Note that a thread is considered as joined only if a previous thread joining is successful. For instance, the thread is not considered as joined in the if branch here:

thrd_t t;
//...
if (thrd_success != thrd_join(t, 0)) {
    /* Thread not considered joined */
}
The analysis cannot detect cases where a joined thread detaches itself using, for instance, the thrd_current() function.

Risk

The C11 standard (clauses 7.26.5.3 and 7.26.5.6) states that a thread shall not be joined or detached once it was previously joined or detached. Violating these clauses of the standard results in undefined behavior.

Fix

Avoid joining a thread that was already joined or detached previously. Likewise, avoid detaching a thread that was already joined or detached.

Example – Joining Followed by Detaching of Thread
#include <stddef.h>
#include <threads.h>
#include <stdlib.h>


extern int thread_func(void *arg);

int main (void)
{
  thrd_t t;

  if (thrd_success != thrd_create (&t, thread_func, NULL)) {
    /* Handle error */
    return 0;
  }

  if (thrd_success != thrd_join (t, 0)) {   
    /* Handle error */
    return 0;
  }

  if (thrd_success != thrd_detach (t)) {    //Noncompliant
    /* Handle error */
    return 0;
  }

  return 0;
}

In this example, the use of thrd_detach on a thread that was previously joined with thrd_join leads to undefined behavior.

To avoid compilation errors with this example, specify the C11 standard with the option C standard version (-c-version).

Correction – Avoid Detaching a Joined Thread

Remove the thrd_join or thrd_detach statement.

#include <stddef.h>
#include <threads.h>
#include <stdlib.h>


extern int thread_func(void *arg);

int main (void)
{
  thrd_t t;

  if (thrd_success != thrd_create (&t, thread_func, NULL)) {
    /* Handle error */
    return 0;
  }

  if (thrd_success != thrd_join (t, 0)) {   
    /* Handle error */
    return 0;
  }

  return 0;
}
Example – Joining Thread Created in Detached State
#include <stddef.h>
#include <pthread.h>
#define thread_success 0

extern void *thread_func(void *arg);


int main() {
    pthread_t id;
    pthread_attr_t attr;
    
    if(thread_success != pthread_attr_init(&attr)) {
        return 0;
    }
   
    if(thread_success != pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED)) {
        return 0;
    }
       
    if(thread_success != pthread_create(&id, &attr, thread_func, NULL)) {
            return 0;
    }
    
    if(thread_success != pthread_join(id, NULL)) { //Noncompliant
            return 0;
    }

    return 0;    
}

In this example, the thread attribute is assigned the state PTHREAD_CREATE_DETACHED. A thread created using this attribute is then joined.

Correction – Create Threads as Joinable

One possible correction is to create a thread with thread attribute assigned to the state PTHREAD_CREATE_JOINABLE and then join the thread.

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

extern void *thread_func(void *arg);


int main() {
    pthread_t id;
    pthread_attr_t attr;
    
    if(thread_success != pthread_attr_init(&attr)) {
        return 0;
    }
   
    if(thread_success != pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE)) {
        return 0;
    }
       
    if(thread_success != pthread_create(&id, &attr, thread_func, NULL)) {
            return 0;
    }
    
    if(thread_success != pthread_join(id, NULL)) {
            return 0;
    }

    return 0;    
}

Check Information

Group: Rule 14. Concurrency (CON)

Version History

Introduced in R2019b


1 This software has been created by MathWorks incorporating portions of: the “SEI CERT-C Website,” © 2017 Carnegie Mellon University, the SEI CERT-C++ Web site © 2017 Carnegie Mellon University, ”SEI CERT C Coding Standard – Rules for Developing safe, Reliable and Secure systems – 2016 Edition,” © 2016 Carnegie Mellon University, and “SEI CERT C++ Coding Standard – Rules for Developing safe, Reliable and Secure systems in C++ – 2016 Edition” © 2016 Carnegie Mellon University, with special permission from its Software Engineering Institute.

ANY MATERIAL OF CARNEGIE MELLON UNIVERSITY AND/OR ITS SOFTWARE ENGINEERING INSTITUTE CONTAINED HEREIN IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.

This software and associated documentation has not been reviewed nor is it endorsed by Carnegie Mellon University or its Software Engineering Institute.