Question

I want to make thread-local buffer for strerror_r call and write my own thread-safe char * my_strerror(int) that will use thread local buffer and call strerror_r.

While reading example regarding pthread_getspecific() in Advanced Programming in Unix Environment by R.Stevens i feel discrepancy - why mutex is used in example below?

Example from book:

#include <limits.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>

static pthread_key_t key;
static pthread_once_t init_done = PTHREAD_ONCE_INIT;
pthread_mutex_t env_mutex = PTHREAD_MUTEX_INITIALIZER;

extern char **environ;

static void
thread_init(void)
{
    pthread_key_create(&key, free);
}

char *
getenv(const char *name)
{
    int     i, len;
    char    *envbuf;

    pthread_once(&init_done, thread_init);
    pthread_mutex_lock(&env_mutex);
    envbuf = (char *)pthread_getspecific(key);
    if (envbuf == NULL) {
        envbuf = malloc(ARG_MAX);
        if (envbuf == NULL) {
            pthread_mutex_unlock(&env_mutex);
            return(NULL);
        }
        pthread_setspecific(key, envbuf);
    }
    len = strlen(name);
    for (i = 0; environ[i] != NULL; i++) {
        if ((strncmp(name, environ[i], len) == 0) &&
          (environ[i][len] == '=')) {
            strcpy(envbuf, &environ[i][len+1]);
            pthread_mutex_unlock(&env_mutex);
            return(envbuf);
        }
    }
    pthread_mutex_unlock(&env_mutex);
    return(NULL);
}

Was it helpful?

Solution

The mutex is needed for the protection of the environ variable, for example, from putenv. The lock call is badly placed, though, it's better to be immediately after the strlen.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top