Pthread: destroying a global static mutex

This code was taken from the 3rd Edition of Advanced UNIX Programming, written by Richard Stevens. This is an example of how to make a reentrant version getenv()

. It is displayed here for training purposes only.

/* Copyright (c) W.R.Stevens */
#include <string.h>
#include <errno.h>
#include <pthread.h>
#include <stdlib.h>

extern char **environ;

pthread_mutex_t env_mutex;

static pthread_once_t init_done = PTHREAD_ONCE_INIT;

static void
thread_init(void)
{
    pthread_mutexattr_t attr;

    pthread_mutexattr_init(&attr);
    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
    pthread_mutex_init(&env_mutex, &attr);
    pthread_mutexattr_destroy(&attr);
}

int
getenv_r(const char *name, char *buf, int buflen)
{
    int i, len, olen;

    pthread_once(&init_done, thread_init);
    len = strlen(name);
    pthread_mutex_lock(&env_mutex);
    for (i = 0; environ[i] != NULL; i++) {
        if ((strncmp(name, environ[i], len) == 0) &&
          (environ[i][len] == '=')) {
            olen = strlen(&environ[i][len+1]);
            if (olen >= buflen) {
                pthread_mutex_unlock(&env_mutex);
                return(ENOSPC);
            }
            strcpy(buf, &environ[i][len+1]);
            pthread_mutex_unlock(&env_mutex);
            return(0);
        }
    }
    pthread_mutex_unlock(&env_mutex);
    return(ENOENT);
}

      

This code is easy to understand. I have a question. We never call pthread_mutex_destroy()

, which means there might be a memory leak on exit (I think it might differ between platforms).

The first thing that comes to mind is what can be used PTHREAD_MUTEX_INITIALIZER

. Is a call required pthread_mutex_init()

? If not, there is no need to call pthread_mutex_destroy()

. However, the mutex will be non-recursive.

It is possible to write a simple C ++ class that could destroy the mutex in the destructor. However, it is not suitable for everyone who only has a C compiler (and it seems to be bullshit for using a C ++ compiler because of one feature).

Another thing that comes to mind is compiler extensions such as __attribute__((destructor))

in GCC (and hopefully clang). However, it is not portable.

Can memory leak be avoided? If so, how can this be done in C?

UPDATE As shown in "Programming with POSIX Threads" by David Butenhof, we never need to destroy a variant PTHREAD_MUTEX_INITIALIZER

. How about mutexes with different attributes?

+3


source to share


2 answers


Resources that are still live when the process terminates are not memory leaks, despite some naive tools classifying them as such. A memory leak is an irreversible and unlimited increase in the resource requirements of a program during its life cycle, which is disproportionate to the actual working set.

In POSIX (where you get POSIX threads), all process-local resources cease to exist when the program terminates. You don't have to explicitly destroy / free them, and in some cases, like you, you cannot safely destroy / free them, and you shouldn't try.



+5


source


There is no memory leak, since the variables pthread_mutex_t

live in user memory, when the process exits, all user allocated memory is returned. Memory leaks occur when something allocates heap memory like strdup. And then you don't clear it.

If it was allocated as



pthread_mutex_t *foo;
....
foo =malloc(sizeof(pthread_mutex_t);

      

And then not freed with free, which creates a memory leak - if then foo got allocated for new memory. However, when the ALL memory process ends, the requested process, including the heap, is restored to the OS. Stevens explains this in the chapter on processes. This code is not leaking.

+1


source







All Articles