Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 24 Jan 2010 10:35:26 +0000 (UTC)
From:      Hajimu UMEMOTO <ume@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r202916 - head/lib/libc/string
Message-ID:  <201001241035.o0OAZQPb098449@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ume
Date: Sun Jan 24 10:35:26 2010
New Revision: 202916
URL: http://svn.freebsd.org/changeset/base/202916

Log:
  Make strsignal(3) thread-safe.
  
  MFC after:	2 weeks

Modified:
  head/lib/libc/string/strsignal.c

Modified: head/lib/libc/string/strsignal.c
==============================================================================
--- head/lib/libc/string/strsignal.c	Sun Jan 24 10:22:39 2010	(r202915)
+++ head/lib/libc/string/strsignal.c	Sun Jan 24 10:35:26 2010	(r202916)
@@ -33,22 +33,64 @@ static char sccsid[] = "@(#)strerror.c	8
 #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;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201001241035.o0OAZQPb098449>