utils: Move thread-safe strerror replacement to a separate file
For some utils _GNU_SOURCE might be needed but that conflicts with the signature of strerror_r(3).
This commit is contained in:
@@ -36,7 +36,8 @@ selectors/traffic_selector.c threading/thread.c threading/thread_value.c \
|
|||||||
threading/mutex.c threading/semaphore.c threading/rwlock.c threading/spinlock.c \
|
threading/mutex.c threading/semaphore.c threading/rwlock.c threading/spinlock.c \
|
||||||
utils/utils.c utils/chunk.c utils/debug.c utils/enum.c utils/identification.c \
|
utils/utils.c utils/chunk.c utils/debug.c utils/enum.c utils/identification.c \
|
||||||
utils/lexparser.c utils/optionsfrom.c utils/capabilities.c utils/backtrace.c \
|
utils/lexparser.c utils/optionsfrom.c utils/capabilities.c utils/backtrace.c \
|
||||||
utils/printf_hook/printf_hook_builtin.c utils/settings.c utils/test.c
|
utils/printf_hook/printf_hook_builtin.c utils/settings.c utils/test.c \
|
||||||
|
utils/utils/strerror.c
|
||||||
|
|
||||||
# adding the plugin source files
|
# adding the plugin source files
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,8 @@ selectors/traffic_selector.c threading/thread.c threading/thread_value.c \
|
|||||||
threading/mutex.c threading/semaphore.c threading/rwlock.c threading/spinlock.c \
|
threading/mutex.c threading/semaphore.c threading/rwlock.c threading/spinlock.c \
|
||||||
utils/utils.c utils/chunk.c utils/debug.c utils/enum.c utils/identification.c \
|
utils/utils.c utils/chunk.c utils/debug.c utils/enum.c utils/identification.c \
|
||||||
utils/lexparser.c utils/optionsfrom.c utils/capabilities.c utils/backtrace.c \
|
utils/lexparser.c utils/optionsfrom.c utils/capabilities.c utils/backtrace.c \
|
||||||
utils/settings.c utils/test.c
|
utils/settings.c utils/test.c \
|
||||||
|
utils/utils/strerror.c
|
||||||
|
|
||||||
if USE_DEV_HEADERS
|
if USE_DEV_HEADERS
|
||||||
strongswan_includedir = ${dev_headers}
|
strongswan_includedir = ${dev_headers}
|
||||||
@@ -82,7 +83,8 @@ utils/utils.h utils/chunk.h utils/debug.h utils/enum.h utils/identification.h \
|
|||||||
utils/lexparser.h utils/optionsfrom.h utils/capabilities.h utils/backtrace.h \
|
utils/lexparser.h utils/optionsfrom.h utils/capabilities.h utils/backtrace.h \
|
||||||
utils/leak_detective.h utils/printf_hook/printf_hook.h \
|
utils/leak_detective.h utils/printf_hook/printf_hook.h \
|
||||||
utils/printf_hook/printf_hook_vstr.h utils/printf_hook/printf_hook_builtin.h \
|
utils/printf_hook/printf_hook_vstr.h utils/printf_hook/printf_hook_builtin.h \
|
||||||
utils/settings.h utils/test.h utils/integrity_checker.h
|
utils/settings.h utils/test.h utils/integrity_checker.h \
|
||||||
|
utils/utils/strerror.h
|
||||||
endif
|
endif
|
||||||
|
|
||||||
library.lo : $(top_builddir)/config.status
|
library.lo : $(top_builddir)/config.status
|
||||||
|
|||||||
@@ -499,7 +499,7 @@ static bool register_hooks()
|
|||||||
char *whitelist[] = {
|
char *whitelist[] = {
|
||||||
/* backtraces, including own */
|
/* backtraces, including own */
|
||||||
"backtrace_create",
|
"backtrace_create",
|
||||||
"safe_strerror",
|
"strerror_safe",
|
||||||
/* pthread stuff */
|
/* pthread stuff */
|
||||||
"pthread_create",
|
"pthread_create",
|
||||||
"pthread_setspecific",
|
"pthread_setspecific",
|
||||||
|
|||||||
@@ -303,84 +303,6 @@ char* tty_escape_get(int fd, tty_escape_t escape)
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* The size of the thread-specific error buffer
|
|
||||||
*/
|
|
||||||
#define STRERROR_BUF_LEN 256
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Key to store thread-specific error buffer
|
|
||||||
*/
|
|
||||||
static pthread_key_t strerror_buf_key;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Only initialize the key above once
|
|
||||||
*/
|
|
||||||
static pthread_once_t strerror_buf_key_once = PTHREAD_ONCE_INIT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create the key used for the thread-specific error buffer
|
|
||||||
*/
|
|
||||||
static void create_strerror_buf_key()
|
|
||||||
{
|
|
||||||
pthread_key_create(&strerror_buf_key, free);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve the error buffer assigned to the current thread (or create it)
|
|
||||||
*/
|
|
||||||
static inline char *get_strerror_buf()
|
|
||||||
{
|
|
||||||
char *buf;
|
|
||||||
|
|
||||||
pthread_once(&strerror_buf_key_once, create_strerror_buf_key);
|
|
||||||
buf = pthread_getspecific(strerror_buf_key);
|
|
||||||
if (!buf)
|
|
||||||
{
|
|
||||||
buf = malloc(STRERROR_BUF_LEN);
|
|
||||||
pthread_setspecific(strerror_buf_key, buf);
|
|
||||||
}
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_STRERROR_R
|
|
||||||
/*
|
|
||||||
* Described in header.
|
|
||||||
*/
|
|
||||||
const char *safe_strerror(int errnum)
|
|
||||||
{
|
|
||||||
char *buf = get_strerror_buf(), *msg;
|
|
||||||
|
|
||||||
#ifdef STRERROR_R_CHAR_P
|
|
||||||
/* char* version which may or may not return the original buffer */
|
|
||||||
msg = strerror_r(errnum, buf, STRERROR_BUF_LEN);
|
|
||||||
#else
|
|
||||||
/* int version returns 0 on success */
|
|
||||||
msg = strerror_r(errnum, buf, STRERROR_BUF_LEN) ? "Unknown error" : buf;
|
|
||||||
#endif
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
#else /* HAVE_STRERROR_R */
|
|
||||||
/* we actually wan't to call strerror(3) below */
|
|
||||||
#undef strerror
|
|
||||||
/*
|
|
||||||
* Described in header.
|
|
||||||
*/
|
|
||||||
const char *safe_strerror(int errnum)
|
|
||||||
{
|
|
||||||
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
||||||
char *buf = get_strerror_buf();
|
|
||||||
|
|
||||||
/* use a mutex to ensure calling strerror(3) is thread-safe */
|
|
||||||
pthread_mutex_lock(&mutex);
|
|
||||||
strncpy(buf, strerror(errnum), STRERROR_BUF_LEN);
|
|
||||||
pthread_mutex_unlock(&mutex);
|
|
||||||
buf[STRERROR_BUF_LEN - 1] = '\0';
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
#endif /* HAVE_STRERROR_R */
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef HAVE_CLOSEFROM
|
#ifndef HAVE_CLOSEFROM
|
||||||
/**
|
/**
|
||||||
* Described in header.
|
* Described in header.
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "enum.h"
|
#include "enum.h"
|
||||||
|
#include "utils/strerror.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* strongSwan program return codes
|
* strongSwan program return codes
|
||||||
@@ -494,23 +495,6 @@ char *strreplace(const char *str, const char *search, const char *replace);
|
|||||||
*/
|
*/
|
||||||
bool mkdir_p(const char *path, mode_t mode);
|
bool mkdir_p(const char *path, mode_t mode);
|
||||||
|
|
||||||
/**
|
|
||||||
* Thread-safe wrapper around strerror and strerror_r.
|
|
||||||
*
|
|
||||||
* This is required because the first is not thread-safe (on some platforms)
|
|
||||||
* and the second uses two different signatures (POSIX/GNU) and is impractical
|
|
||||||
* to use anyway.
|
|
||||||
*
|
|
||||||
* @param errnum error code (i.e. errno)
|
|
||||||
* @return error message
|
|
||||||
*/
|
|
||||||
const char *safe_strerror(int errnum);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Replace usages of strerror(3) with thread-safe variant.
|
|
||||||
*/
|
|
||||||
#define strerror(errnum) safe_strerror(errnum)
|
|
||||||
|
|
||||||
#ifndef HAVE_CLOSEFROM
|
#ifndef HAVE_CLOSEFROM
|
||||||
/**
|
/**
|
||||||
* Close open file descriptors greater than or equal to lowfd.
|
* Close open file descriptors greater than or equal to lowfd.
|
||||||
|
|||||||
@@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2012-2014 Tobias Brunner
|
||||||
|
* Hochschule fuer Technik Rapperswil
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2 of the License, or (at your
|
||||||
|
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#include "strerror.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The size of the thread-specific error buffer
|
||||||
|
*/
|
||||||
|
#define STRERROR_BUF_LEN 256
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key to store thread-specific error buffer
|
||||||
|
*/
|
||||||
|
static pthread_key_t strerror_buf_key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Only initialize the key above once
|
||||||
|
*/
|
||||||
|
static pthread_once_t strerror_buf_key_once = PTHREAD_ONCE_INIT;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the key used for the thread-specific error buffer
|
||||||
|
*/
|
||||||
|
static void create_strerror_buf_key()
|
||||||
|
{
|
||||||
|
pthread_key_create(&strerror_buf_key, free);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the error buffer assigned to the current thread (or create it)
|
||||||
|
*/
|
||||||
|
static inline char *get_strerror_buf()
|
||||||
|
{
|
||||||
|
char *buf;
|
||||||
|
|
||||||
|
pthread_once(&strerror_buf_key_once, create_strerror_buf_key);
|
||||||
|
buf = pthread_getspecific(strerror_buf_key);
|
||||||
|
if (!buf)
|
||||||
|
{
|
||||||
|
buf = malloc(STRERROR_BUF_LEN);
|
||||||
|
pthread_setspecific(strerror_buf_key, buf);
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_STRERROR_R
|
||||||
|
/*
|
||||||
|
* Described in header.
|
||||||
|
*/
|
||||||
|
const char *strerror_safe(int errnum)
|
||||||
|
{
|
||||||
|
char *buf = get_strerror_buf(), *msg;
|
||||||
|
|
||||||
|
#ifdef STRERROR_R_CHAR_P
|
||||||
|
/* char* version which may or may not return the original buffer */
|
||||||
|
msg = strerror_r(errnum, buf, STRERROR_BUF_LEN);
|
||||||
|
#else
|
||||||
|
/* int version returns 0 on success */
|
||||||
|
msg = strerror_r(errnum, buf, STRERROR_BUF_LEN) ? "Unknown error" : buf;
|
||||||
|
#endif
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
#else /* HAVE_STRERROR_R */
|
||||||
|
/* we actually wan't to call strerror(3) below */
|
||||||
|
#undef strerror
|
||||||
|
/*
|
||||||
|
* Described in header.
|
||||||
|
*/
|
||||||
|
const char *strerror_safe(int errnum)
|
||||||
|
{
|
||||||
|
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
char *buf = get_strerror_buf();
|
||||||
|
|
||||||
|
/* use a mutex to ensure calling strerror(3) is thread-safe */
|
||||||
|
pthread_mutex_lock(&mutex);
|
||||||
|
strncpy(buf, strerror(errnum), STRERROR_BUF_LEN);
|
||||||
|
pthread_mutex_unlock(&mutex);
|
||||||
|
buf[STRERROR_BUF_LEN - 1] = '\0';
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
#endif /* HAVE_STRERROR_R */
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2012-2014 Tobias Brunner
|
||||||
|
* Hochschule fuer Technik Rapperswil
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2 of the License, or (at your
|
||||||
|
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @{ @ingroup utils
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef STRERROR_H_
|
||||||
|
#define STRERROR_H_
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thread-safe wrapper around strerror and strerror_r.
|
||||||
|
*
|
||||||
|
* This is required because the first is not thread-safe (on some platforms)
|
||||||
|
* and the second uses two different signatures (POSIX/GNU) and is impractical
|
||||||
|
* to use anyway.
|
||||||
|
*
|
||||||
|
* @param errnum error code (i.e. errno)
|
||||||
|
* @return error message
|
||||||
|
*/
|
||||||
|
const char *strerror_safe(int errnum);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replace usages of strerror(3) with thread-safe variant.
|
||||||
|
*/
|
||||||
|
#define strerror(errnum) strerror_safe(errnum)
|
||||||
|
|
||||||
|
#endif /** STRERROR_H_ @}*/
|
||||||
Reference in New Issue
Block a user