diff options
author | Paul Pluzhnikov <ppluzhnikov@google.com> | 2013-12-18 15:07:11 -0800 |
---|---|---|
committer | Paul Pluzhnikov <ppluzhnikov@google.com> | 2013-12-18 15:07:11 -0800 |
commit | 69a17d9d245dc3551792e95e1823cc2d877592f3 (patch) | |
tree | 719f3789f573b05c6c168f3720048acd42420ea4 /sysdeps/unix | |
parent | a588438951a271ca10623fb8c7e25693c7ebea67 (diff) | |
download | glibc-69a17d9d245dc3551792e95e1823cc2d877592f3.tar glibc-69a17d9d245dc3551792e95e1823cc2d877592f3.tar.gz glibc-69a17d9d245dc3551792e95e1823cc2d877592f3.tar.bz2 glibc-69a17d9d245dc3551792e95e1823cc2d877592f3.zip |
Patch [1/4] async-signal safe TLS.
2013-12-18 Andrew Hunter <ahh@google.com>
* sysdeps/generic/ldsodefs.h (_dl_mask_all_signals): New prototype.
(_dl_unmask_signals): Likewise.
* sysdeps/mach/hurd/dl-sysdep.h (_dl_mask_all_signals): New stub.
(_dl_unmask_all_signals): Likewise.
* sysdeps/unix/sysv/linux/dl-sysdep.h (_dl_mask_all_signals): New prototype.
(_dl_unmask_all_signals): Likewise.
* sysdeps/unix/sysv/linux/dl-sysdep.c (_dl_mask_all_signals): New function.
(_dl_unmask_signals): Likewise.
Diffstat (limited to 'sysdeps/unix')
-rw-r--r-- | sysdeps/unix/sysv/linux/dl-sysdep.c | 46 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/dl-sysdep.h | 4 |
2 files changed, 50 insertions, 0 deletions
diff --git a/sysdeps/unix/sysv/linux/dl-sysdep.c b/sysdeps/unix/sysv/linux/dl-sysdep.c index e80cb8d9f0..4b837acbc0 100644 --- a/sysdeps/unix/sysv/linux/dl-sysdep.c +++ b/sysdeps/unix/sysv/linux/dl-sysdep.c @@ -19,6 +19,7 @@ /* Linux needs some special initialization, but otherwise uses the generic dynamic linker system interface code. */ +#include <assert.h> #include <string.h> #include <fcntl.h> #include <unistd.h> @@ -130,3 +131,48 @@ _dl_discover_osversion (void) return version; } + +/* Mask every signal, returning the previous sigmask in OLD. */ +void +internal_function +_dl_mask_all_signals (sigset_t *old) +{ + int ret; + sigset_t new; + + sigfillset (&new); + + /* This function serves as a replacement to pthread_sigmask, which + isn't available from within the dynamic linker since it would require + linking with libpthread. We duplicate some of the functionality here + to avoid requiring libpthread. This isn't quite identical to + pthread_sigmask in that we do not mask internal signals used for + cancellation and setxid handling. This disables asynchronous + cancellation for the duration the signals are disabled, but it's a + small window, and prevents any problems with the use of TLS variables + in the signal handlers that would have executed. */ + + /* It's very important we don't touch errno here, as that's TLS; since this + gets called from get_tls_addr we might end up recursing. */ + + INTERNAL_SYSCALL_DECL (err); + + ret = INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &new, old, + _NSIG / 8); + + assert (ret == 0); +} + +/* Return sigmask to what it was before a call to _dl_mask_all_signals. */ +void +internal_function +_dl_unmask_signals (sigset_t *old) +{ + int ret; + INTERNAL_SYSCALL_DECL (err); + + ret = INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, old, NULL, + _NSIG / 8); + + assert (ret == 0); +} diff --git a/sysdeps/unix/sysv/linux/dl-sysdep.h b/sysdeps/unix/sysv/linux/dl-sysdep.h index e1eab09025..0fe1e1c3d0 100644 --- a/sysdeps/unix/sysv/linux/dl-sysdep.h +++ b/sysdeps/unix/sysv/linux/dl-sysdep.h @@ -30,4 +30,8 @@ /* Get version of the OS. */ extern int _dl_discover_osversion (void) attribute_hidden; # define HAVE_DL_DISCOVER_OSVERSION 1 + +#include <signal.h> +void _dl_mask_all_signals (sigset_t *) internal_function; +void _dl_unmask_all_signals (sigset_t *) internal_function; #endif |