diff options
author | Andrew Hunter <ahh@google.com> | 2015-10-13 10:39:00 -0700 |
---|---|---|
committer | Andrew Hunter <ahh@google.com> | 2015-10-13 10:39:00 -0700 |
commit | 497c190870c07e031da4f7b558f9ab816839a86e (patch) | |
tree | ff49b3a2a7a6261f8811081fa8e8faee1f89c52b | |
parent | 14cfc78089e4839598f9e8116268704eb35a2970 (diff) | |
download | glibc-497c190870c07e031da4f7b558f9ab816839a86e.tar.gz glibc-497c190870c07e031da4f7b558f9ab816839a86e.tar.xz glibc-497c190870c07e031da4f7b558f9ab816839a86e.zip |
Make pthread_getspecific async-signal-safe
-rw-r--r-- | README.google | 4 | ||||
-rw-r--r-- | nptl/Makefile | 4 | ||||
-rw-r--r-- | nptl/pthread_getspecific.c | 12 | ||||
-rw-r--r-- | nptl/tst-key5.c | 77 |
4 files changed, 87 insertions, 10 deletions
diff --git a/README.google b/README.google index a6550c99b9..1d7fa8e88e 100644 --- a/README.google +++ b/README.google @@ -503,3 +503,7 @@ elf/dl-load.c For b/22641205, #include _itoa.h (ppluzhnikov, google-local) +nptl/pthread_getspecific.c +nptl/tst-key5.c + Fix for b/18722637 : make pthread_getspecific signal safe. + (ahh, google-local, proposed upstream) diff --git a/nptl/Makefile b/nptl/Makefile index f57b0b84c4..f669d1a3cc 100644 --- a/nptl/Makefile +++ b/nptl/Makefile @@ -228,7 +228,7 @@ tests = tst-typesizes \ tst-rwlock5 tst-rwlock6 tst-rwlock7 tst-rwlock8 tst-rwlock9 \ tst-rwlock10 tst-rwlock11 tst-rwlock12 tst-rwlock13 tst-rwlock14 \ tst-once1 tst-once2 tst-once3 tst-once4 \ - tst-key1 tst-key2 tst-key3 tst-key4 \ + tst-key1 tst-key2 tst-key3 tst-key4 tst-key5 \ tst-sem1 tst-sem2 tst-sem3 tst-sem4 tst-sem5 tst-sem6 tst-sem7 \ tst-sem8 tst-sem9 tst-sem10 tst-sem11 tst-sem12 tst-sem13 tst-sem14 \ tst-barrier1 tst-barrier2 tst-barrier3 tst-barrier4 \ @@ -609,6 +609,8 @@ $(objpfx)tst-execstack: $(libdl) $(objpfx)tst-execstack.out: $(objpfx)tst-execstack-mod.so LDFLAGS-tst-execstack = -Wl,-z,noexecstack +LDFLAGS-tst-key5 = -lrt + $(objpfx)tst-fini1mod.so: $(shared-thread-library) tst-stackguard1-ARGS = --command "$(host-test-program-cmd) --child" diff --git a/nptl/pthread_getspecific.c b/nptl/pthread_getspecific.c index e0e7daca24..8248dc358f 100644 --- a/nptl/pthread_getspecific.c +++ b/nptl/pthread_getspecific.c @@ -53,16 +53,10 @@ __pthread_getspecific (key) data = &level2[idx2nd]; } - void *result = data->data; - if (result != NULL) - { - uintptr_t seq = data->seq; - - if (__builtin_expect (seq != __pthread_keys[key].seq, 0)) - result = data->data = NULL; - } + if (__builtin_expect (data->seq != __pthread_keys[key].seq, 0)) + return NULL; - return result; + return data->data; } strong_alias (__pthread_getspecific, pthread_getspecific) hidden_def (__pthread_getspecific) diff --git a/nptl/tst-key5.c b/nptl/tst-key5.c new file mode 100644 index 0000000000..b5cdbf9c11 --- /dev/null +++ b/nptl/tst-key5.c @@ -0,0 +1,77 @@ +/* Copyright (C) 2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <pthread.h> +#include <unistd.h> +#include <signal.h> +#include <time.h> +#include <assert.h> +#include <string.h> +#include <stdio.h> + + +pthread_key_t key; +void *value; +size_t r; +static void +handler (int signo) +{ + void *ret = pthread_getspecific (key); + /* We race with the setspecific--either result is fine, just not junk. */ + assert (ret == value || ret == NULL); + r++; +} + + +int +do_test (void) +{ + struct sigaction sa; + memset (&sa, 0, sizeof (sa)); + sa.sa_handler = handler; + + assert (0 == sigaction (SIGUSR1, &sa, NULL)); + + timer_t timer; + struct sigevent sevp; + sevp.sigev_notify = SIGEV_SIGNAL; + sevp.sigev_signo = SIGUSR1; + assert (0 == timer_create(CLOCK_MONOTONIC, &sevp, &timer)); + struct itimerspec spec; + spec.it_value.tv_sec = 0; + spec.it_value.tv_nsec = 500; + spec.it_interval = spec.it_value; + timer_settime(timer, 0, &spec, NULL); +#define NITERS (1000 * 1000) + for (int i = 0; i < NITERS; ++i) + { + value = (void *)((intptr_t)i + 1); + assert (0 == pthread_key_create(&key, NULL)); + assert (0 == pthread_setspecific(key, value)); + if (value != pthread_getspecific(key)) + { + printf ("Lost a value\n"); + return 1; + } + assert (0 == pthread_key_delete(key)); + } + timer_delete(timer); + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" |