diff options
author | ume <ume@FreeBSD.org> | 2010-01-24 10:35:26 +0000 |
---|---|---|
committer | ume <ume@FreeBSD.org> | 2010-01-24 10:35:26 +0000 |
commit | 613ef8622623d2439e73e28d105485935e979d44 (patch) | |
tree | 34d50dc5596c9ee1f897b3826073fc4332a11c70 /lib/libc/string | |
parent | 5fa77a0084e7088758903647e5c5d7fba99e815e (diff) | |
download | FreeBSD-src-613ef8622623d2439e73e28d105485935e979d44.zip FreeBSD-src-613ef8622623d2439e73e28d105485935e979d44.tar.gz |
Make strsignal(3) thread-safe.
MFC after: 2 weeks
Diffstat (limited to 'lib/libc/string')
-rw-r--r-- | lib/libc/string/strsignal.c | 52 |
1 files changed, 48 insertions, 4 deletions
diff --git a/lib/libc/string/strsignal.c b/lib/libc/string/strsignal.c index e4267a3..c51f34d 100644 --- a/lib/libc/string/strsignal.c +++ b/lib/libc/string/strsignal.c @@ -33,22 +33,64 @@ static char sccsid[] = "@(#)strerror.c 8.1 (Berkeley) 6/4/93"; #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); +#include "namespace.h" #if defined(NLS) #include <nl_types.h> #endif - #include <limits.h> #include <errno.h> +#include <stdlib.h> #include <string.h> #include <signal.h> +#include "reentrant.h" +#include "un-namespace.h" #define UPREFIX "Unknown signal" +static char sig_ebuf[NL_TEXTMAX]; +static char sig_ebuf_err[NL_TEXTMAX]; +static once_t sig_init_once = ONCE_INITIALIZER; +static thread_key_t sig_key; +static int sig_keycreated = 0; + +static void +sig_keycreate(void) +{ + sig_keycreated = (thr_keycreate(&sig_key, free) == 0); +} + +static char * +sig_tlsalloc(void) +{ + char *ebuf = NULL; + + if (thr_main() != 0) + ebuf = sig_ebuf; + else { + if (thr_once(&sig_init_once, sig_keycreate) != 0 || + !sig_keycreated) + goto thr_err; + if ((ebuf = thr_getspecific(sig_key)) == NULL) { + if ((ebuf = malloc(sizeof(sig_ebuf))) == NULL) + goto thr_err; + if (thr_setspecific(sig_key, ebuf) != 0) { + free(ebuf); + ebuf = NULL; + goto thr_err; + } + } + } +thr_err: + if (ebuf == NULL) + ebuf = sig_ebuf_err; + return (ebuf); +} + /* XXX: negative 'num' ? (REGR) */ char * strsignal(int num) { - static char ebuf[NL_TEXTMAX]; + char *ebuf; char tmp[20]; size_t n; int signum; @@ -60,6 +102,8 @@ strsignal(int num) catd = catopen("libc", NL_CAT_LOCALE); #endif + ebuf = sig_tlsalloc(); + if (num > 0 && num < sys_nsig) { n = strlcpy(ebuf, #if defined(NLS) @@ -67,7 +111,7 @@ strsignal(int num) #else sys_siglist[num], #endif - sizeof(ebuf)); + sizeof(sig_ebuf)); } else { n = strlcpy(ebuf, #if defined(NLS) @@ -75,7 +119,7 @@ strsignal(int num) #else UPREFIX, #endif - sizeof(ebuf)); + sizeof(sig_ebuf)); } signum = num; |