Use pthread_create properly to prevent memory leaks

Source: Internet
Author: User

Recently, I heard that pthread_create will cause memory leaks, it is incredible, so the POSIX (NPTL) thread creation and destruction are analyzed.
Analysis results: If used incorrectly, it does cause a memory leak. Root cause: Pthread_create The thread created by default is detached. Prevention: either create a detached thread, or the thread thread start_routine before the end of detached, or join
The analysis process is as follows:
1. View the Pthread_create source code, the core code is as follows (NPTL/PTHREAD_CREATE.C):

Click (here) to collapse or open int
__pthread_create_2_1 (Newthread, attr, Start_routine, Arg)
pthread_t *newthread;
Const pthread_attr_t *ATTR;
void * (*start_routine) (void *);
void *arg;
{
Stack_variables;

const struct PTHREAD_ATTR *iattr = (struct pthread_attr *) attr;
if (iattr = NULL)
* Is this best idea? On NUMA machines This could mean
accessing Far-away memory. */
Iattr = &default_attr;

struct Pthread *pd = NULL;
int err = Allocate_stack (iattr, &PD);//Allocate memory for TCB
if (__builtin_expect (Err!= 0, 0))
/* something went wrong. Maybe a parameter of the attributes is
Invalid or we could not allocate memory. */
return err; ... err = Create_thread (PD, IATTR, Stack_variables_args); formally create thread

2. View CREATETHREAD.C (NPTL/SYSDEPS/PTHREAD/CREATETHREAD.C)

Click (here) to collapse or open the static int
Create_thread (struct pthread *pd, const struct PTHREAD_ATTR,
Stack_variables_parms)
{
#ifdef TLS_TCB_AT_TP
ASSERT (PD->HEADER.TCB!= NULL);
#endif///...
int res = Do_clone (PD, attr, Clone_flags, Start_thread, Stack_variables_args, 1);//clone a process 3. Then look at the start What did _thread (nptl/pthread_create.c) do?

Click (here) to collapse or open the static int
Start_thread (void *arg)
{
struct Pthread *pd = (struct pthread *) arg;
......

/* Run The code the user provided. */
#ifdef CALL_THREAD_FCT
Thread_setmem (PD, result, CALL_THREAD_FCT (PD));
#else
Thread_setmem (PD, result, Pd->start_routine (Pd->arg)); Officially start the execution of the thread and wait for execution to complete
#endif//... if (is_detached (PD))/* Free the TCB. //__FREE_TCB (PD);//If the detached flag is set, the content occupied by the TCB is released, otherwise it is returned directly to else if (__builtin_expect pd->cancelhandling & Setxid  _bitmask, 0)) {/* Some other thread might-call all of the SETXID functions and expect us to reply.  In the case wait until we did that.       * * Do lll_futex_wait (&pd->setxid_futex, 0, lll_private); while (Pd->cancelhandling & Setxid_bitmask);
* Reset The value so this stack can be reused.     * * Pd->setxid_futex = 0; From the above procedure, we can see that if the detached flag is not set when the thread is created, TCB memory will never be released
Next, let's look at what Pthread_detach (NPTH/PTHREAD_DETACH.C) did.

Click (here) to collapse or open int
Pthread_detach (TH)
pthread_t th;
{
struct Pthread *pd = (struct pthread *) th;

/* Make sure the descriptor is valid. */
if (Invalid_not_terminated_td_p (PD))
/* Not a valid thread handle. */
return esrch;

int result = 0;

* Mark the thread as detached. */
if (Atomic_compare_and_exchange_bool_acq (&pd->joinid, PD, NULL))
{
/* There are two possibilities here. The thread might
Already be detached. We return einval.
Otherwise there might already be a waiter. The standard does
Not mention what happens in the this case. */
if (is_detached (PD))
result = Einval;
}
Else
/* Check Whether the thread terminated meanwhile. In the case we
Would just free the TCB. */
if ((Pd->cancelhandling & Exiting_bitmask)!= 0)
/* Note This code in __FREE_TCB makes sure each thread
Control's freed only once. */
__FREE_TCB (PD);//through a series of fault-tolerant judgment, direct release TCB occupied memory

return result;
Finally, let's take a look at what Pthread_join (NPTL/PTHREAD_JOIN.C) did

Click (here) to collapse or open int
pthread_join  (threadid, thread_return)
     pthread _t ThreadID;
     void **thread_return;
{
  struct pthread *pd =  (struct pthread *)  threadid;

  /* make sure the descriptor is valid. */
  if  (invalid_not_ terminated_td_p  (PD))
    /* not a valid thread handle. */
     return Esrch

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.