1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-07-28 00:21:52 +03:00

string: Remove old TLS usage on strsignal

The per-thread state is refactored two use two strategies:

  1. The default one uses a TLS structure, which will be placed in the
     static TLS space (using __thread keyword).

  2. Linux allocates via struct pthread and access it through THREAD_*
     macros.

The default strategy has the disadvantage of increasing libc.so static
TLS consumption and thus decreasing the possible surplus used in
some scenarios (which might be mitigated by BZ#25051 fix).

It is used only on Hurd, where accessing the thread storage in the in
single thread case is not straightforward (afaiu, Hurd developers could
correct me here).

The fallback static allocation used for allocation failure is also
removed: defining its size is problematic without synchronizing with
translated messages (to avoid partial translation) and the resulting
usage is not thread-safe.

Checked on x86-64-linux-gnu, i686-linux-gnu, powerpc64le-linux-gnu,
and s390x-linux-gnu.

Tested-by: Carlos O'Donell <carlos@redhat.com>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
This commit is contained in:
Adhemerval Zanella
2020-05-14 17:02:38 -03:00
parent f26d456b98
commit 9deec7c8ba
10 changed files with 156 additions and 92 deletions

View File

@ -20,106 +20,36 @@
#include <stdlib.h>
#include <string.h>
#include <libintl.h>
#include <libc-lock.h>
static __libc_key_t key;
/* If nonzero the key allocation failed and we should better use a
static buffer than fail. */
#define BUFFERSIZ 100
static char local_buf[BUFFERSIZ];
static char *static_buf;
/* Destructor for the thread-specific data. */
static void init (void);
static void free_key_mem (void *mem);
static char *getbuffer (void);
#include <tls-internal.h>
#include <array_length.h>
/* Return a string describing the meaning of the signal number SIGNUM. */
char *
strsignal (int signum)
{
__libc_once_define (static, once);
const char *desc;
const char *desc = NULL;
/* If we have not yet initialized the buffer do it now. */
__libc_once (once, init);
if (signum >= 0 && signum <= NSIG && signum < array_length (__sys_siglist))
desc = __sys_siglist[signum];
if (
if (desc != NULL)
return (char *) _(desc);
struct tls_internal_t *tls_internal = __glibc_tls_internal ();
free (tls_internal->strsignal_buf);
int r;
#ifdef SIGRTMIN
(signum >= SIGRTMIN && signum <= SIGRTMAX) ||
#endif
signum < 0 || signum >= NSIG
|| (desc = __sys_siglist[signum]) == NULL)
{
char *buffer = getbuffer ();
int len;
#ifdef SIGRTMIN
if (signum >= SIGRTMIN && signum <= SIGRTMAX)
len = __snprintf (buffer, BUFFERSIZ - 1, _("Real-time signal %d"),
signum - SIGRTMIN);
else
#endif
len = __snprintf (buffer, BUFFERSIZ - 1, _("Unknown signal %d"),
signum);
if (len >= BUFFERSIZ)
buffer = NULL;
else
buffer[len] = '\0';
return buffer;
}
return (char *) _(desc);
}
/* Initialize buffer. */
static void
init (void)
{
if (__libc_key_create (&key, free_key_mem))
/* Creating the key failed. This means something really went
wrong. In any case use a static buffer which is better than
nothing. */
static_buf = local_buf;
}
/* Free the thread specific data, this is done if a thread terminates. */
static void
free_key_mem (void *mem)
{
free (mem);
__libc_setspecific (key, NULL);
}
/* Return the buffer to be used. */
static char *
getbuffer (void)
{
char *result;
if (static_buf != NULL)
result = static_buf;
if (signum >= SIGRTMIN && signum <= SIGRTMAX)
r = __asprintf (&tls_internal->strsignal_buf, _("Real-time signal %d"),
signum - SIGRTMIN);
else
{
/* We don't use the static buffer and so we have a key. Use it
to get the thread-specific buffer. */
result = __libc_getspecific (key);
if (result == NULL)
{
/* No buffer allocated so far. */
result = malloc (BUFFERSIZ);
if (result == NULL)
/* No more memory available. We use the static buffer. */
result = local_buf;
else
__libc_setspecific (key, result);
}
}
#endif
r = __asprintf (&tls_internal->strsignal_buf, _("Unknown signal %d"),
signum);
return result;
if (r == -1)
tls_internal->strsignal_buf = NULL;
return tls_internal->strsignal_buf;
}