Author: ume
Date: Sun Feb  7 04:27:18 2010
New Revision: 203598
URL: http://svn.freebsd.org/changeset/base/203598

Log:
  MFC r202916: Make strsignal(3) thread-safe.

Modified:
  stable/8/lib/libc/string/strsignal.c
Directory Properties:
  stable/8/lib/libc/   (props changed)
  stable/8/lib/libc/stdtime/   (props changed)

Modified: stable/8/lib/libc/string/strsignal.c
==============================================================================
--- stable/8/lib/libc/string/strsignal.c        Sun Feb  7 04:24:10 2010        
(r203597)
+++ stable/8/lib/libc/string/strsignal.c        Sun Feb  7 04:27:18 2010        
(r203598)
@@ -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;
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to