summaryrefslogtreecommitdiffstats
path: root/lib/libc/string
diff options
context:
space:
mode:
authorume <ume@FreeBSD.org>2010-01-24 10:35:26 +0000
committerume <ume@FreeBSD.org>2010-01-24 10:35:26 +0000
commit613ef8622623d2439e73e28d105485935e979d44 (patch)
tree34d50dc5596c9ee1f897b3826073fc4332a11c70 /lib/libc/string
parent5fa77a0084e7088758903647e5c5d7fba99e815e (diff)
downloadFreeBSD-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.c52
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;
OpenPOWER on IntegriCloud