diff options
author | 2015-04-07 01:27:06 +0000 | |
---|---|---|
committer | 2015-04-07 01:27:06 +0000 | |
commit | 514a545f8a3983d53b7de4e8dfcefe16c9496776 (patch) | |
tree | e17cf0966466dfd49a1decf34dd536d3fdbe4765 | |
parent | Do not mistreat empty arguments to font alternating macros (diff) | |
download | wireguard-openbsd-514a545f8a3983d53b7de4e8dfcefe16c9496776.tar.xz wireguard-openbsd-514a545f8a3983d53b7de4e8dfcefe16c9496776.zip |
Make pthread_atfork() track the DSO that called it like atexit() does,
unregistering callbacks if the DSO is unloaded. Move the callback
handling from libpthread to libc, though libpthread still overrides the
inner call to handle locking and thread-library reinitialization.
Major version bump for both libc and libpthread.
verification that this fixes various ports ajacoutot@
asm assistance miod@; ok millert@ deraadt@
46 files changed, 557 insertions, 129 deletions
diff --git a/lib/csu/crtbegin.c b/lib/csu/crtbegin.c index e1ffc16bb1b..2917bd38260 100644 --- a/lib/csu/crtbegin.c +++ b/lib/csu/crtbegin.c @@ -1,4 +1,4 @@ -/* $OpenBSD: crtbegin.c,v 1.18 2015/04/04 18:05:05 guenther Exp $ */ +/* $OpenBSD: crtbegin.c,v 1.19 2015/04/07 01:27:06 guenther Exp $ */ /* $NetBSD: crtbegin.c,v 1.1 1996/09/12 16:59:03 cgd Exp $ */ /* @@ -91,6 +91,19 @@ atexit(void (*fn)(void)) return (__cxa_atexit((void (*)(void *))fn, NULL, NULL)); } +/* + * Ditto for pthread_atfork() + */ +int _thread_atfork(void (*)(void), void (*)(void), void (*)(void), void *) + __attribute__((weak)); + +int +pthread_atfork(void (*prep)(void), void (*parent)(void), void (*child)(void)) +{ + return (_thread_atfork(prep, parent, child, NULL)); +} +asm(".weak pthread_atfork"); + static const init_f __CTOR_LIST__[1] __attribute__((section(".ctors"))) = { (void *)-1 }; /* XXX */ diff --git a/lib/csu/crtbeginS.c b/lib/csu/crtbeginS.c index 152bfa5ec79..f97d30f22b0 100644 --- a/lib/csu/crtbeginS.c +++ b/lib/csu/crtbeginS.c @@ -1,4 +1,4 @@ -/* $OpenBSD: crtbeginS.c,v 1.15 2015/04/04 18:05:05 guenther Exp $ */ +/* $OpenBSD: crtbeginS.c,v 1.16 2015/04/07 01:27:06 guenther Exp $ */ /* $NetBSD: crtbegin.c,v 1.1 1996/09/12 16:59:03 cgd Exp $ */ /* @@ -80,6 +80,20 @@ atexit(void (*fn)(void)) } asm(".hidden atexit"); +/* + * Ditto for pthread_atfork() + */ +int _thread_atfork(void (*)(void), void (*)(void), void (*)(void), void *) + __attribute__((weak)); + +int +pthread_atfork(void (*prep)(void), void (*parent)(void), void (*child)(void)) +{ + return (_thread_atfork(prep, parent, child, &__dso_handle)); +} +/* hppa doesn't permit directives in first column, so space after newline */ +asm(".hidden pthread_atfork\n .weak pthread_atfork"); + static init_f __CTOR_LIST__[1] __attribute__((section(".ctors"))) = { (void *)-1 }; /* XXX */ diff --git a/lib/libc/arch/alpha/SYS.h b/lib/libc/arch/alpha/SYS.h index bc2ea4ca888..f1d15c6a501 100644 --- a/lib/libc/arch/alpha/SYS.h +++ b/lib/libc/arch/alpha/SYS.h @@ -1,4 +1,4 @@ -/* $OpenBSD: SYS.h,v 1.9 2002/10/06 23:23:18 art Exp $ */ +/* $OpenBSD: SYS.h,v 1.10 2015/04/07 01:27:06 guenther Exp $ */ /* $NetBSD: SYS.h,v 1.4 1996/10/17 03:03:53 cgd Exp $ */ /* @@ -90,6 +90,7 @@ __END(p,label); __SYSCALL_NOERROR(_thread_sys_,x) # define RSYSCALL(x) ALIAS(_thread_sys_,x) \ __RSYSCALL(_thread_sys_,x) +# define RSYSCALL_HIDDEN(x) __RSYSCALL(_thread_sys_,x) # define RSYSCALL_NOERROR(x) ALIAS(_thread_sys_,x) \ __RSYSCALL_NOERROR(_thread_sys_,x) # define PSEUDO(x,y) ALIAS(_thread_sys_,x) \ diff --git a/lib/libc/arch/alpha/sys/fork.S b/lib/libc/arch/alpha/sys/fork.S index d2509858586..59b96139585 100644 --- a/lib/libc/arch/alpha/sys/fork.S +++ b/lib/libc/arch/alpha/sys/fork.S @@ -1,4 +1,4 @@ -/* $OpenBSD: fork.S,v 1.6 2015/03/31 04:32:01 guenther Exp $ */ +/* $OpenBSD: fork.S,v 1.7 2015/04/07 01:27:06 guenther Exp $ */ /* $NetBSD: fork.S,v 1.1 1995/02/10 17:50:34 cgd Exp $ */ /* @@ -30,4 +30,5 @@ #include "SYS.h" -RSYSCALL(fork) +RSYSCALL_HIDDEN(fork) +WEAK_ALIAS(_thread_fork,_thread_sys_fork) diff --git a/lib/libc/arch/amd64/SYS.h b/lib/libc/arch/amd64/SYS.h index f5710a879c4..82eedd460fc 100644 --- a/lib/libc/arch/amd64/SYS.h +++ b/lib/libc/arch/amd64/SYS.h @@ -1,4 +1,4 @@ -/* $OpenBSD: SYS.h,v 1.9 2014/06/04 20:13:49 matthew Exp $ */ +/* $OpenBSD: SYS.h,v 1.10 2015/04/07 01:27:06 guenther Exp $ */ /*- * Copyright (c) 1990 The Regents of the University of California. @@ -40,10 +40,13 @@ #define SYSTRAP(x) movl $(SYS_ ## x),%eax; movq %rcx, %r10; syscall + #define SYSENTRY(x) \ ENTRY(_thread_sys_ ## x); \ .weak _C_LABEL(x); \ _C_LABEL(x) = _C_LABEL(_thread_sys_ ## x) +#define SYSENTRY_HIDDEN(x) \ + ENTRY(_thread_sys_ ## x) \ #define CERROR _C_LABEL(__cerror) #define _CERROR _C_LABEL(___cerror) @@ -52,6 +55,9 @@ #define _SYSCALL_NOERROR(x,y) \ SYSENTRY(x); \ SYSTRAP(y) +#define _SYSCALL_HIDDEN_NOERROR(x,y) \ + SYSENTRY_HIDDEN(x); \ + SYSTRAP(y) #ifdef __PIC__ #define _SYSCALL(x,y) \ @@ -60,12 +66,23 @@ jmp *%rcx; \ _SYSCALL_NOERROR(x,y); \ jc 2b +#define _SYSCALL_HIDDEN(x,y) \ + .text; _ALIGN_TEXT; \ + 2: mov PIC_GOT(CERROR), %rcx; \ + jmp *%rcx; \ + _SYSCALL_HIDDEN_NOERROR(x,y); \ + jc 2b #else #define _SYSCALL(x,y) \ .text; _ALIGN_TEXT; \ 2: jmp CERROR; \ _SYSCALL_NOERROR(x,y); \ jc 2b +#define _SYSCALL_HIDDEN(x,y) \ + .text; _ALIGN_TEXT; \ + 2: jmp CERROR; \ + _SYSCALL_HIDDEN_NOERROR(x,y); \ + jc 2b #endif #define SYSCALL_NOERROR(x) \ @@ -81,15 +98,16 @@ #define PSEUDO(x,y) \ _SYSCALL(x,y); \ ret +#define PSEUDO_HIDDEN(x,y) \ + _SYSCALL_HIDDEN(x,y); \ + ret #define RSYSCALL_NOERROR(x) \ PSEUDO_NOERROR(x,x) #define RSYSCALL(x) \ PSEUDO(x,x) - -#define WSYSCALL(weak,strong) \ - WEAK_ALIAS(weak,strong); \ - PSEUDO(strong,weak) +#define RSYSCALL_HIDDEN(x) \ + PSEUDO_HIDDEN(x,x) .globl CERROR diff --git a/lib/libc/arch/amd64/sys/fork.S b/lib/libc/arch/amd64/sys/fork.S index d0a2ea33178..6582d8a9a32 100644 --- a/lib/libc/arch/amd64/sys/fork.S +++ b/lib/libc/arch/amd64/sys/fork.S @@ -1,4 +1,4 @@ -/* $OpenBSD: fork.S,v 1.3 2015/03/31 04:32:01 guenther Exp $ */ +/* $OpenBSD: fork.S,v 1.4 2015/04/07 01:27:06 guenther Exp $ */ /* $NetBSD: fork.S,v 1.2 2003/02/13 02:50:51 nathanw Exp $ */ /*- @@ -39,4 +39,5 @@ #include "SYS.h" -RSYSCALL(fork) +RSYSCALL_HIDDEN(fork) +WEAK_ALIAS(_thread_fork,_thread_sys_fork) diff --git a/lib/libc/arch/arm/SYS.h b/lib/libc/arch/arm/SYS.h index c6cfdbc4fcd..2fb7c3a91ba 100644 --- a/lib/libc/arch/arm/SYS.h +++ b/lib/libc/arch/arm/SYS.h @@ -1,4 +1,4 @@ -/* $OpenBSD: SYS.h,v 1.8 2015/03/31 12:31:19 jsing Exp $ */ +/* $OpenBSD: SYS.h,v 1.9 2015/04/07 01:27:06 guenther Exp $ */ /* $NetBSD: SYS.h,v 1.8 2003/08/07 16:42:02 agc Exp $ */ /*- @@ -42,6 +42,8 @@ .weak _C_LABEL(x); \ _C_LABEL(x) = _C_LABEL(_thread_sys_ ## x); \ ENTRY(_thread_sys_ ## x) +#define SYSENTRY_HIDDEN(x) \ + ENTRY(_thread_sys_ ## x) #define SYSTRAP(x) \ ldr r12, =SYS_ ## x; \ @@ -54,10 +56,16 @@ #define _SYSCALL_NOERROR(x,y) \ SYSENTRY(x); \ SYSTRAP(y) +#define _SYSCALL_HIDDEN_NOERROR(x,y) \ + SYSENTRY_HIDDEN(x); \ + SYSTRAP(y) #define _SYSCALL(x, y) \ _SYSCALL_NOERROR(x,y); \ bcs PIC_SYM(CERROR, PLT) +#define _SYSCALL_HIDDEN(x, y) \ + _SYSCALL_HIDDEN_NOERROR(x,y); \ + bcs PIC_SYM(CERROR, PLT) #define SYSCALL_NOERROR(x) \ _SYSCALL_NOERROR(x,x) @@ -73,6 +81,9 @@ #define PSEUDO(x,y) \ _SYSCALL(x,y); \ mov r15, r14 +#define PSEUDO_HIDDEN(x,y) \ + _SYSCALL_HIDDEN(x,y); \ + mov r15, r14 #define RSYSCALL_NOERROR(x) \ @@ -80,5 +91,7 @@ #define RSYSCALL(x) \ PSEUDO(x,x) +#define RSYSCALL_HIDDEN(x) \ + PSEUDO_HIDDEN(x,x) .globl CERROR diff --git a/lib/libc/arch/arm/sys/fork.S b/lib/libc/arch/arm/sys/fork.S index 9836d80a975..8d92b286369 100644 --- a/lib/libc/arch/arm/sys/fork.S +++ b/lib/libc/arch/arm/sys/fork.S @@ -1,4 +1,4 @@ -/* $OpenBSD: fork.S,v 1.3 2015/03/31 04:32:01 guenther Exp $ */ +/* $OpenBSD: fork.S,v 1.4 2015/04/07 01:27:06 guenther Exp $ */ /* $NetBSD: fork.S,v 1.5 2003/08/07 16:42:04 agc Exp $ */ /*- @@ -34,4 +34,5 @@ #include "SYS.h" -RSYSCALL(fork) +RSYSCALL_HIDDEN(fork) +WEAK_ALIAS(_thread_fork,_thread_sys_fork) diff --git a/lib/libc/arch/hppa/SYS.h b/lib/libc/arch/hppa/SYS.h index 2c1f6a8e9e1..a2dbef50244 100644 --- a/lib/libc/arch/hppa/SYS.h +++ b/lib/libc/arch/hppa/SYS.h @@ -1,4 +1,4 @@ -/* $OpenBSD: SYS.h,v 1.16 2010/10/01 05:02:19 guenther Exp $ */ +/* $OpenBSD: SYS.h,v 1.17 2015/04/07 01:27:06 guenther Exp $ */ /* * Copyright (c) 1998-2002 Michael Shalayeff @@ -36,6 +36,8 @@ #define SYSENTRY(x) !\ LEAF_ENTRY(__CONCAT(_thread_sys_,x)) !\ WEAK_ALIAS(x,__CONCAT(_thread_sys_,x)) +#define SYSENTRY_HIDDEN(x) !\ +LEAF_ENTRY(__CONCAT(_thread_sys_,x)) #define SYSEXIT(x) !\ EXIT(__CONCAT(_thread_sys_,x)) @@ -54,6 +56,12 @@ SYSENTRY(x) !\ bv r0(rp) !\ nop !\ SYSEXIT(x) +#define PSEUDO_HIDDEN(x,y) !\ +SYSENTRY_HIDDEN(x) !\ + SYSCALL(y) !\ + bv r0(rp) !\ + nop !\ +SYSEXIT(x) #define PSEUDO_NOERROR(x,y) !\ SYSENTRY(x) !\ @@ -66,5 +74,6 @@ SYSENTRY(x) !\ nop !\ SYSEXIT(x) -#define RSYSCALL(x) PSEUDO(x,x) +#define RSYSCALL(x) PSEUDO(x,x) +#define RSYSCALL_HIDDEN(x) PSEUDO_HIDDEN(x,x) diff --git a/lib/libc/arch/hppa/sys/fork.S b/lib/libc/arch/hppa/sys/fork.S index 6a4efd8f3de..8bb3bc545b9 100644 --- a/lib/libc/arch/hppa/sys/fork.S +++ b/lib/libc/arch/hppa/sys/fork.S @@ -1,4 +1,4 @@ -/* $OpenBSD: fork.S,v 1.12 2015/03/31 04:32:01 guenther Exp $ */ +/* $OpenBSD: fork.S,v 1.13 2015/04/07 01:27:06 guenther Exp $ */ /* * Copyright (c) 1999 Michael Shalayeff @@ -28,4 +28,5 @@ #include "SYS.h" -RSYSCALL(fork) +RSYSCALL_HIDDEN(fork) +WEAK_ALIAS(_thread_fork,_thread_sys_fork) diff --git a/lib/libc/arch/hppa64/SYS.h b/lib/libc/arch/hppa64/SYS.h index d60f389285d..510ab2c5fba 100644 --- a/lib/libc/arch/hppa64/SYS.h +++ b/lib/libc/arch/hppa64/SYS.h @@ -1,4 +1,4 @@ -/* $OpenBSD: SYS.h,v 1.6 2011/09/19 13:01:28 kettenis Exp $ */ +/* $OpenBSD: SYS.h,v 1.7 2015/04/07 01:27:06 guenther Exp $ */ /* * Copyright (c) 1998-2002 Michael Shalayeff @@ -36,6 +36,8 @@ #define SYSENTRY(x) !\ LEAF_ENTRY(__CONCAT(_thread_sys_,x)) !\ WEAK_ALIAS(x,__CONCAT(_thread_sys_,x)) +#define SYSENTRY_HIDDEN(x) !\ +LEAF_ENTRY(__CONCAT(_thread_sys_,x)) #define SYSEXIT(x) !\ EXIT(__CONCAT(_thread_sys_,x)) @@ -56,6 +58,12 @@ SYSENTRY(x) !\ bv %r0(%rp) !\ nop !\ SYSEXIT(x) +#define PSEUDO_HIDDEN(x,y) !\ +SYSENTRY_HIDDEN(x) !\ + SYSCALL(y) !\ + bv %r0(%rp) !\ + nop !\ +SYSEXIT(x) #define PSEUDO_NOERROR(x,y) !\ SYSENTRY(x) !\ @@ -69,5 +77,6 @@ SYSENTRY(x) !\ nop !\ SYSEXIT(x) -#define RSYSCALL(x) PSEUDO(x,x) +#define RSYSCALL(x) PSEUDO(x,x) +#define RSYSCALL_HIDDEN(x) PSEUDO_HIDDEN(x,x) diff --git a/lib/libc/arch/hppa64/sys/fork.S b/lib/libc/arch/hppa64/sys/fork.S index ce870ec4024..7602c801601 100644 --- a/lib/libc/arch/hppa64/sys/fork.S +++ b/lib/libc/arch/hppa64/sys/fork.S @@ -1,4 +1,4 @@ -/* $OpenBSD: fork.S,v 1.5 2015/03/31 04:32:01 guenther Exp $ */ +/* $OpenBSD: fork.S,v 1.6 2015/04/07 01:27:06 guenther Exp $ */ /* * Copyright (c) 1999 Michael Shalayeff @@ -28,4 +28,5 @@ #include "SYS.h" -RSYSCALL(fork) +RSYSCALL_HIDDEN(fork) +WEAK_ALIAS(_thread_fork,_thread_sys_fork) diff --git a/lib/libc/arch/i386/SYS.h b/lib/libc/arch/i386/SYS.h index cc199d6bf3d..a6c1c852c03 100644 --- a/lib/libc/arch/i386/SYS.h +++ b/lib/libc/arch/i386/SYS.h @@ -29,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: SYS.h,v 1.19 2014/06/04 20:13:49 matthew Exp $ + * $OpenBSD: SYS.h,v 1.20 2015/04/07 01:27:06 guenther Exp $ */ #include <machine/asm.h> @@ -49,6 +49,8 @@ ENTRY(_thread_sys_ ## x); \ .weak _C_LABEL(x); \ _C_LABEL(x) = _C_LABEL(_thread_sys_ ## x) +#define SYSENTRY_HIDDEN(x) \ + ENTRY(_thread_sys_ ## x) #define __DO_SYSCALL(x) \ movl $(SYS_ ## x),%eax; \ @@ -62,6 +64,9 @@ #define _SYSCALL_NOERROR(x,y) \ SYSENTRY(x); \ __DO_SYSCALL(y); +#define _SYSCALL_HIDDEN_NOERROR(x,y) \ + SYSENTRY_HIDDEN(x); \ + __DO_SYSCALL(y); #define SYSCALL_NOERROR(x) \ _SYSCALL_NOERROR(x,x) @@ -77,6 +82,15 @@ jmp *%ecx; \ _SYSCALL_NOERROR(x,y) \ jc 2b +#define _SYSCALL_HIDDEN(x,y) \ + .text; \ + .align 2; \ + 2: PIC_PROLOGUE; \ + movl PIC_GOT(CERROR), %ecx; \ + PIC_EPILOGUE; \ + jmp *%ecx; \ + _SYSCALL_HIDDEN_NOERROR(x,y) \ + jc 2b #else #define _SYSCALL(x,y) \ .text; \ @@ -85,6 +99,13 @@ jmp PIC_PLT(CERROR); \ _SYSCALL_NOERROR(x,y) \ jc 2b +#define _SYSCALL_HIDDEN(x,y) \ + .text; \ + .align 2; \ + 2: \ + jmp PIC_PLT(CERROR); \ + _SYSCALL_HIDDEN_NOERROR(x,y) \ + jc 2b #endif #define SYSCALL(x) \ @@ -99,9 +120,14 @@ #define PSEUDO(x,y) \ _SYSCALL(x,y); \ ret +#define PSEUDO_HIDDEN(x,y) \ + _SYSCALL_HIDDEN(x,y); \ + ret /* perform a syscall with the same name, set errno, return */ #define RSYSCALL(x) \ PSEUDO(x,x); +#define RSYSCALL_HIDDEN(x) \ + PSEUDO_HIDDEN(x,x) .globl CERROR diff --git a/lib/libc/arch/i386/sys/fork.S b/lib/libc/arch/i386/sys/fork.S index 205ae5942c1..1e750d3f0d6 100644 --- a/lib/libc/arch/i386/sys/fork.S +++ b/lib/libc/arch/i386/sys/fork.S @@ -1,4 +1,4 @@ -/* $OpenBSD: fork.S,v 1.5 2015/03/31 04:32:01 guenther Exp $ */ +/* $OpenBSD: fork.S,v 1.6 2015/04/07 01:27:06 guenther Exp $ */ /*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. @@ -33,4 +33,5 @@ #include "SYS.h" -RSYSCALL(fork) +RSYSCALL_HIDDEN(fork) +WEAK_ALIAS(_thread_fork,_thread_sys_fork) diff --git a/lib/libc/arch/m88k/SYS.h b/lib/libc/arch/m88k/SYS.h index 9d6de9d755e..70292c9d585 100644 --- a/lib/libc/arch/m88k/SYS.h +++ b/lib/libc/arch/m88k/SYS.h @@ -1,4 +1,4 @@ -/* $OpenBSD: SYS.h,v 1.18 2014/06/04 20:13:49 matthew Exp $*/ +/* $OpenBSD: SYS.h,v 1.19 2015/04/07 01:27:06 guenther Exp $*/ /*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. @@ -83,10 +83,16 @@ __ENTRY(p,x); \ __ALIAS(p,x); \ __DO_SYSCALL(y) +#define __SYSCALL_HIDDEN__NOERROR(p,x,y) \ + __ENTRY(p,x); \ + __DO_SYSCALL(y) #define __SYSCALL(p,x,y) \ __SYSCALL__NOERROR(p,x,y); \ br CERROR +#define __SYSCALL_HIDDEN(p,x,y) \ + __SYSCALL_HIDDEN__NOERROR(p,x,y); \ + br CERROR #define __PSEUDO_NOERROR(p,x,y) \ __SYSCALL__NOERROR(p,x,y); \ @@ -97,6 +103,10 @@ __SYSCALL(p,x,y); \ jmp %r1; \ __END(p,x) +#define __PSEUDO_HIDDEN(p,x,y) \ + __SYSCALL_HIDDEN(p,x,y); \ + jmp %r1; \ + __END(p,x) /* * System calls entry points are really named _thread_sys_{syscall}, @@ -105,6 +115,7 @@ */ #define SYSCALL(x) __SYSCALL(_thread_sys_,x,x) #define RSYSCALL(x) __PSEUDO(_thread_sys_,x,x) +#define RSYSCALL_HIDDEN(x) __PSEUDO_HIDDEN(_thread_sys_,x,x) #define PSEUDO(x,y) __PSEUDO(_thread_sys_,x,y) #define PSEUDO_NOERROR(x,y) __PSEUDO_NOERROR(_thread_sys_,x,y) #define SYSENTRY(x) __ENTRY(_thread_sys_,x); \ diff --git a/lib/libc/arch/m88k/sys/fork.S b/lib/libc/arch/m88k/sys/fork.S index 3c88e9f65d0..2c664f74fd2 100644 --- a/lib/libc/arch/m88k/sys/fork.S +++ b/lib/libc/arch/m88k/sys/fork.S @@ -1,4 +1,4 @@ -/* $OpenBSD: fork.S,v 1.8 2013/09/08 18:01:56 miod Exp $ */ +/* $OpenBSD: fork.S,v 1.9 2015/04/07 01:27:06 guenther Exp $ */ /*- * Copyright (c) 1990 The Regents of the University of California. @@ -35,4 +35,5 @@ #include "SYS.h" -RSYSCALL(fork) +RSYSCALL_HIDDEN(fork) +WEAK_ALIAS(_thread_fork,_thread_sys_fork) diff --git a/lib/libc/arch/mips64/SYS.h b/lib/libc/arch/mips64/SYS.h index 885ca700cec..55926724eb9 100644 --- a/lib/libc/arch/mips64/SYS.h +++ b/lib/libc/arch/mips64/SYS.h @@ -29,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: SYS.h,v 1.6 2014/06/04 20:13:49 matthew Exp $ + * $OpenBSD: SYS.h,v 1.7 2015/04/07 01:27:06 guenther Exp $ */ #include <sys/syscall.h> @@ -71,9 +71,24 @@ PTR_ADDU sp,32; \ jr t9; \ __END2(p,x) +#define __PSEUDO_HIDDEN(p,x,y) \ + LEAF(p ## x,32); \ + PTR_SUBU sp,32; \ + SETUP_GP64(16,__CLABEL2(p,x)); \ + __DO_SYSCALL(y); \ + bne a3,zero,err; \ + RESTORE_GP64; \ + PTR_ADDU sp,32; \ + j ra; \ + err: LA t9,CERROR; \ + RESTORE_GP64; \ + PTR_ADDU sp,32; \ + jr t9; \ + END(p ## x) #define RSYSCALL(x) __PSEUDO(_thread_sys_,x,x) +#define RSYSCALL_HIDDEN(x) __PSEUDO_HIDDEN(_thread_sys_,x,x) #define PSEUDO(x,y) __PSEUDO(_thread_sys_,x,y) #define PSEUDO_NOERROR(x,y) __PSEUDO_NOERROR(_thread_sys_,x,y) diff --git a/lib/libc/arch/mips64/sys/fork.S b/lib/libc/arch/mips64/sys/fork.S index 39aebd47385..be3b2851414 100644 --- a/lib/libc/arch/mips64/sys/fork.S +++ b/lib/libc/arch/mips64/sys/fork.S @@ -1,4 +1,4 @@ -/* $OpenBSD: fork.S,v 1.6 2015/03/31 04:32:02 guenther Exp $ */ +/* $OpenBSD: fork.S,v 1.7 2015/04/07 01:27:06 guenther Exp $ */ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. @@ -33,4 +33,5 @@ #include "SYS.h" -RSYSCALL(fork) +RSYSCALL_HIDDEN(fork) +WEAK_ALIAS(_thread_fork,_thread_sys_fork) diff --git a/lib/libc/arch/powerpc/SYS.h b/lib/libc/arch/powerpc/SYS.h index 218c49f5878..fdd4e8913e3 100644 --- a/lib/libc/arch/powerpc/SYS.h +++ b/lib/libc/arch/powerpc/SYS.h @@ -1,4 +1,4 @@ -/* $OpenBSD: SYS.h,v 1.15 2014/06/04 20:13:49 matthew Exp $ */ +/* $OpenBSD: SYS.h,v 1.16 2015/04/07 01:27:06 guenther Exp $ */ /*- * Copyright (c) 1994 * Andrew Cagney. All rights reserved. @@ -68,9 +68,11 @@ sc ; \ PSEUDO_NOERROR_SUFFIX -#define PSEUDO(x,y) ALIAS(_thread_sys_,x) \ - PSEUDO_PREFIX(_thread_sys_,x,y) ; \ +#define PSEUDO_HIDDEN(x,y) PSEUDO_PREFIX(_thread_sys_,x,y) ; \ sc ; \ PSEUDO_SUFFIX +#define PSEUDO(x,y) ALIAS(_thread_sys_,x) \ + PSEUDO_HIDDEN(x,y) #define RSYSCALL(x) PSEUDO(x,x) +#define RSYSCALL_HIDDEN(x) PSEUDO_HIDDEN(x,x) diff --git a/lib/libc/arch/powerpc/sys/fork.S b/lib/libc/arch/powerpc/sys/fork.S index d07de61737b..ace55a4a4d1 100644 --- a/lib/libc/arch/powerpc/sys/fork.S +++ b/lib/libc/arch/powerpc/sys/fork.S @@ -1,4 +1,4 @@ -/* $OpenBSD: fork.S,v 1.2 2002/10/07 04:47:12 drahn Exp $ */ +/* $OpenBSD: fork.S,v 1.3 2015/04/07 01:27:06 guenther Exp $ */ /* * Copyright (c) 1996 Dale Rahn @@ -29,4 +29,5 @@ #include "SYS.h" -RSYSCALL(fork) +RSYSCALL_HIDDEN(fork) +WEAK_ALIAS(_thread_fork,_thread_sys_fork) diff --git a/lib/libc/arch/sh/SYS.h b/lib/libc/arch/sh/SYS.h index 4a9f22ac32c..468e265c947 100644 --- a/lib/libc/arch/sh/SYS.h +++ b/lib/libc/arch/sh/SYS.h @@ -1,4 +1,4 @@ -/* $OpenBSD: SYS.h,v 1.5 2014/06/04 20:13:49 matthew Exp $ */ +/* $OpenBSD: SYS.h,v 1.6 2015/04/07 01:27:06 guenther Exp $ */ /*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. @@ -40,6 +40,8 @@ #define SYSENTRY(x) \ WEAK_ALIAS(x,_thread_sys_ ## x); \ ENTRY(_thread_sys_ ## x) +#define SYSENTRY_HIDDEN(x) \ + ENTRY(_thread_sys_ ## x) #define SYSTRAP(x) \ mov.l 903f, r0; \ @@ -56,6 +58,9 @@ #define _SYSCALL_NOERROR(x,y) \ SYSENTRY(x); \ SYSTRAP(y) +#define _SYSCALL_HIDDEN_NOERROR(x,y) \ + SYSENTRY_HIDDEN(x); \ + SYSTRAP(y) #ifdef __PIC__ @@ -88,6 +93,11 @@ 911: JUMP_CERROR; \ _SYSCALL_NOERROR(x,y); \ bf 911b +#define _SYSCALL_HIDDEN(x,y) \ + .text; \ + 911: JUMP_CERROR; \ + _SYSCALL_HIDDEN_NOERROR(x,y); \ + bf 911b #define SYSCALL_NOERROR(x) \ _SYSCALL_NOERROR(x,x) @@ -105,10 +115,13 @@ rts; \ nop -#define RSYSCALL_NOERROR(x) \ - PSEUDO_NOERROR(x,x) +#define PSEUDO_HIDDEN(x,y) \ + _SYSCALL_HIDDEN(x,y); \ + rts; \ + nop -#define RSYSCALL(x) \ - PSEUDO(x,x) +#define RSYSCALL_NOERROR(x) PSEUDO_NOERROR(x,x) +#define RSYSCALL(x) PSEUDO(x,x) +#define RSYSCALL_HIDDEN(x) PSEUDO_HIDDEN(x,x) .globl CERROR diff --git a/lib/libc/arch/sh/sys/fork.S b/lib/libc/arch/sh/sys/fork.S index cf552fd07b2..4ee5a0442df 100644 --- a/lib/libc/arch/sh/sys/fork.S +++ b/lib/libc/arch/sh/sys/fork.S @@ -1,4 +1,4 @@ -/* $OpenBSD: fork.S,v 1.3 2015/03/31 04:32:02 guenther Exp $ */ +/* $OpenBSD: fork.S,v 1.4 2015/04/07 01:27:07 guenther Exp $ */ /* $NetBSD: fork.S,v 1.10 2006/01/06 05:11:29 uwe Exp $ */ /*- @@ -37,4 +37,5 @@ #include "SYS.h" -RSYSCALL(fork) +RSYSCALL_HIDDEN(fork) +WEAK_ALIAS(_thread_fork,_thread_sys_fork) diff --git a/lib/libc/arch/sparc/SYS.h b/lib/libc/arch/sparc/SYS.h index f010285062d..729c386bfaa 100644 --- a/lib/libc/arch/sparc/SYS.h +++ b/lib/libc/arch/sparc/SYS.h @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: SYS.h,v 1.16 2014/06/04 20:13:49 matthew Exp $ + * $OpenBSD: SYS.h,v 1.17 2015/04/07 01:27:07 guenther Exp $ */ #include <machine/asm.h> @@ -39,7 +39,8 @@ #define _CAT(x,y) x##y -#define __ENTRY(p,x) ENTRY(_CAT(p,x)) ; .weak x ; x = _CAT(p,x) +#define __ENTRY(p,x) ENTRY(_CAT(p,x)) ; .weak x ; x = _CAT(p,x) +#define __ENTRY_HIDDEN(p,x) ENTRY(_CAT(p,x)) /* * ERROR branches to cerror. @@ -71,6 +72,8 @@ */ #define __SYSCALL(p,x) \ __ENTRY(p,x); mov _CAT(SYS_,x),%g1; t ST_SYSCALL; bcc 1f; nop; ERROR(); 1: +#define __SYSCALL_HIDDEN(p,x) \ + __ENTRY_HIDDEN(p,x); mov _CAT(SYS_,x),%g1; t ST_SYSCALL; bcc 1f; nop; ERROR(); 1: /* * RSYSCALL is used when the system call should just return. Here @@ -97,6 +100,7 @@ # define SYSCALL(x) __SYSCALL(_thread_sys_,x) # define RSYSCALL(x) __RSYSCALL(_thread_sys_,x) +# define RSYSCALL_HIDDEN(x) __RSYSCALL(_thread_sys_,x) # define PSEUDO(x,y) __PSEUDO(_thread_sys_,x,y) # define PSEUDO_NOERROR(x,y) __PSEUDO_NOERROR(_thread_sys_,x,y) # define SYSENTRY(x) __ENTRY(_thread_sys_,x) diff --git a/lib/libc/arch/sparc/sys/fork.S b/lib/libc/arch/sparc/sys/fork.S index 83916669e78..911fce204dd 100644 --- a/lib/libc/arch/sparc/sys/fork.S +++ b/lib/libc/arch/sparc/sys/fork.S @@ -1,4 +1,4 @@ -/* $OpenBSD: fork.S,v 1.5 2015/03/31 04:32:02 guenther Exp $ */ +/* $OpenBSD: fork.S,v 1.6 2015/04/07 01:27:07 guenther Exp $ */ /* * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. @@ -34,4 +34,5 @@ #include "SYS.h" -RSYSCALL(fork) +RSYSCALL_HIDDEN(fork) +WEAK_ALIAS(_thread_fork,_thread_sys_fork) diff --git a/lib/libc/arch/sparc64/SYS.h b/lib/libc/arch/sparc64/SYS.h index f47a4d47da7..3f934da0323 100644 --- a/lib/libc/arch/sparc64/SYS.h +++ b/lib/libc/arch/sparc64/SYS.h @@ -1,4 +1,4 @@ -/* $OpenBSD: SYS.h,v 1.11 2014/06/04 20:13:49 matthew Exp $ */ +/* $OpenBSD: SYS.h,v 1.12 2015/04/07 01:27:07 guenther Exp $ */ /*- * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. @@ -43,7 +43,8 @@ #define _CAT(x,y) x##y -#define __ENTRY(p,x) ENTRY(_CAT(p,x)) ; .weak x; x = _CAT(p,x) +#define __ENTRY(p,x) ENTRY(_CAT(p,x)) ; .weak x; x = _CAT(p,x) +#define __ENTRY_HIDDEN(p,x) ENTRY(_CAT(p,x)) /* * ERROR branches to cerror. This is done with a macro so that I can @@ -71,18 +72,26 @@ */ #define _SYSCALL(p,x,y) \ __ENTRY(p,x); mov _CAT(SYS_,y),%g1; t ST_SYSCALL; bcc 1f; nop; ERROR(); 1: +#define _SYSCALL_HIDDEN(p,x,y) \ + __ENTRY_HIDDEN(p,x); mov _CAT(SYS_,y),%g1; t ST_SYSCALL; bcc 1f; nop; ERROR(); 1: #define __SYSCALL(p,x) \ _SYSCALL(p,x,x) +#define __SYSCALL_HIDDEN(p,x) \ + _SYSCALL_HIDDEN(p,x,x) + /* * RSYSCALL is used when the system call should just return. Here * we use the SYSCALL_G2RFLAG to put the `success' return address in %g2 * and avoid a branch. */ #define __RSYSCALL(p,x) \ - __ENTRY(p,x); mov (_CAT(SYS_,x))|SYSCALL_G2RFLAG,%g1; add %o7,8,%g2; \ - t ST_SYSCALL; ERROR() + __ENTRY(p,x); mov (_CAT(SYS_,x))|SYSCALL_G2RFLAG,%g1; \ + add %o7,8,%g2; t ST_SYSCALL; ERROR() +#define __RSYSCALL_HIDDEN(p,x) \ + __ENTRY_HIDDEN(p,x); mov (_CAT(SYS_,x))|SYSCALL_G2RFLAG,%g1; \ + add %o7,8,%g2; t ST_SYSCALL; ERROR() /* * PSEUDO(x,y) is like RSYSCALL(y) except that the name is x. @@ -126,6 +135,7 @@ #define SYSCALL(x) __SYSCALL(_thread_sys_,x) #define RSYSCALL(x) __RSYSCALL(_thread_sys_,x) +#define RSYSCALL_HIDDEN(x) __RSYSCALL_HIDDEN(_thread_sys_,x) #define RSYSCALL_NOERROR(x,y) __RSYSCALL_NOERROR(_thread_sys_,x,y) #define PSEUDO(x,y) __PSEUDO(_thread_sys_,x,y) #define PSEUDO_NOERROR(x,y) __PSEUDO_NOERROR(_thread_sys_,x,y) diff --git a/lib/libc/arch/sparc64/sys/fork.S b/lib/libc/arch/sparc64/sys/fork.S index ffb32b62ad0..f432448d4ad 100644 --- a/lib/libc/arch/sparc64/sys/fork.S +++ b/lib/libc/arch/sparc64/sys/fork.S @@ -1,4 +1,4 @@ -/* $OpenBSD: fork.S,v 1.3 2015/03/31 04:32:02 guenther Exp $ */ +/* $OpenBSD: fork.S,v 1.4 2015/04/07 01:27:07 guenther Exp $ */ /* * Copyright (c) 1992, 1993 @@ -37,4 +37,5 @@ #include "SYS.h" -RSYSCALL(fork) +RSYSCALL_HIDDEN(fork) +WEAK_ALIAS(_thread_fork,_thread_sys_fork) diff --git a/lib/libc/arch/vax/SYS.h b/lib/libc/arch/vax/SYS.h index 816c700f2ff..2449243f186 100644 --- a/lib/libc/arch/vax/SYS.h +++ b/lib/libc/arch/vax/SYS.h @@ -1,4 +1,4 @@ -/* $OpenBSD: SYS.h,v 1.16 2014/06/04 20:13:49 matthew Exp $ */ +/* $OpenBSD: SYS.h,v 1.17 2015/04/07 01:27:07 guenther Exp $ */ /* $NetBSD: SYS.h,v 1.4 1997/05/02 18:15:32 kleink Exp $ */ /* @@ -66,6 +66,7 @@ __SYSCALL(_thread_sys_,x,x) #define RSYSCALL(x) __ALIAS(_thread_sys_,x) \ __PSEUDO(_thread_sys_,x,x) +#define RSYSCALL_HIDDEN(x) __PSEUDO(_thread_sys_,x,x) #define PSEUDO(x,y) __ALIAS(_thread_sys_,x) \ __PSEUDO(_thread_sys_,x,y) #define PSEUDO_NOERROR(x,y) __ALIAS(_thread_sys_,x) \ diff --git a/lib/libc/arch/vax/sys/fork.S b/lib/libc/arch/vax/sys/fork.S index 9204b5af8b2..4848c1e21ec 100644 --- a/lib/libc/arch/vax/sys/fork.S +++ b/lib/libc/arch/vax/sys/fork.S @@ -1,4 +1,4 @@ -/* $OpenBSD: fork.S,v 1.6 2015/03/31 04:32:02 guenther Exp $ */ +/* $OpenBSD: fork.S,v 1.7 2015/04/07 01:27:07 guenther Exp $ */ /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -30,4 +30,5 @@ #include "SYS.h" -RSYSCALL(fork) +RSYSCALL_HIDDEN(fork) +WEAK_ALIAS(_thread_fork,_thread_sys_fork) diff --git a/lib/libc/include/atfork.h b/lib/libc/include/atfork.h new file mode 100644 index 00000000000..8ec611098c1 --- /dev/null +++ b/lib/libc/include/atfork.h @@ -0,0 +1,44 @@ +/* $OpenBSD: atfork.h,v 1.1 2015/04/07 01:27:07 guenther Exp $ */ + +/* + * Copyright (c) 2008 Kurt Miller <kurt@openbsd.org> + * Copyright (c) 2008 Philip Guenther <guenther@openbsd.org> + * Copyright (c) 2003 Daniel Eischen <deischen@freebsd.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: /repoman/r/ncvs/src/lib/libc_r/uthread/uthread_atfork.c,v 1.1 2004/12/10 03:36:45 grog Exp $ + */ + +#include <sys/queue.h> + +struct atfork_fn { + TAILQ_ENTRY(atfork_fn) fn_next; + void (*fn_prepare)(void); + void (*fn_parent)(void); + void (*fn_child)(void); + void *fn_dso; +}; + +extern TAILQ_HEAD(atfork_listhead, atfork_fn) _atfork_list; + diff --git a/lib/libc/include/thread_private.h b/lib/libc/include/thread_private.h index 673fb9c6a69..43ebf7d96e8 100644 --- a/lib/libc/include/thread_private.h +++ b/lib/libc/include/thread_private.h @@ -1,4 +1,4 @@ -/* $OpenBSD: thread_private.h,v 1.25 2011/10/16 06:29:56 guenther Exp $ */ +/* $OpenBSD: thread_private.h,v 1.26 2015/04/07 01:27:07 guenther Exp $ */ /* PUBLIC DOMAIN: No Rights Reserved. Marco S Hyman <marc@snafu.org> */ @@ -160,6 +160,18 @@ void _thread_atexit_unlock(void); _thread_atexit_unlock();\ } while (0) +void _thread_atfork_lock(void); +void _thread_atfork_unlock(void); + +#define _ATFORK_LOCK() do { \ + if (__isthreaded) \ + _thread_atfork_lock(); \ + } while (0) +#define _ATFORK_UNLOCK() do { \ + if (__isthreaded) \ + _thread_atfork_unlock();\ + } while (0) + void _thread_arc4_lock(void); void _thread_arc4_unlock(void); @@ -172,4 +184,9 @@ void _thread_arc4_unlock(void); _thread_arc4_unlock();\ } while (0) +/* + * Wrapper for _thread_sys_fork() + */ +pid_t _thread_fork(void); + #endif /* _THREAD_PRIVATE_H_ */ diff --git a/lib/libc/shlib_version b/lib/libc/shlib_version index 72264f2e9ce..add7e4a9c1c 100644 --- a/lib/libc/shlib_version +++ b/lib/libc/shlib_version @@ -1,4 +1,4 @@ -major=78 -minor=1 +major=79 +minor=0 # note: If changes were made to include/thread_private.h or if system # calls were added/changed then librthread/shlib_version also be updated. diff --git a/lib/libc/stdlib/atexit.c b/lib/libc/stdlib/atexit.c index 6532b382eab..a33080571fe 100644 --- a/lib/libc/stdlib/atexit.c +++ b/lib/libc/stdlib/atexit.c @@ -1,4 +1,4 @@ -/* $OpenBSD: atexit.c,v 1.20 2014/07/11 09:51:37 kettenis Exp $ */ +/* $OpenBSD: atexit.c,v 1.21 2015/04/07 01:27:07 guenther Exp $ */ /* * Copyright (c) 2002 Daniel Hartmeier * All rights reserved. @@ -35,6 +35,7 @@ #include <string.h> #include <unistd.h> #include "atexit.h" +#include "atfork.h" #include "thread_private.h" struct atexit *__atexit; @@ -161,6 +162,23 @@ restart: __atexit = NULL; } _ATEXIT_UNLOCK(); + + /* + * If unloading a DSO, unregister any atfork handlers registered + * by it. Skip the locking if the list is currently empty. + */ + if (dso != NULL && TAILQ_FIRST(&_atfork_list) != NULL) { + struct atfork_fn *af, *afnext; + + _ATFORK_LOCK(); + TAILQ_FOREACH_SAFE(af, &_atfork_list, fn_next, afnext) + if (af->fn_dso == dso) { + TAILQ_REMOVE(&_atfork_list, af, fn_next); + free(af); + } + _ATFORK_UNLOCK(); + + } } /* diff --git a/lib/libc/sys/Makefile.inc b/lib/libc/sys/Makefile.inc index 6cf739c5530..ee9b8ff6737 100644 --- a/lib/libc/sys/Makefile.inc +++ b/lib/libc/sys/Makefile.inc @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile.inc,v 1.124 2014/12/08 20:56:11 guenther Exp $ +# $OpenBSD: Makefile.inc,v 1.125 2015/04/07 01:27:07 guenther Exp $ # $NetBSD: Makefile.inc,v 1.35 1995/10/16 23:49:07 jtc Exp $ # @(#)Makefile.inc 8.1 (Berkeley) 6/17/93 @@ -11,7 +11,7 @@ SRCS+= Ovfork.S brk.S cerror.S exect.S fork.S \ sigsuspend.S syscall.S tfork_thread.S # glue to offer userland wrappers for some syscalls -SRCS+= posix_madvise.c +SRCS+= posix_madvise.c w_fork.c # glue to provide compatibility between GCC 1.X and 2.X and for compat # with old syscall interfaces. diff --git a/lib/libc/sys/w_fork.c b/lib/libc/sys/w_fork.c new file mode 100644 index 00000000000..1c6080e0cbd --- /dev/null +++ b/lib/libc/sys/w_fork.c @@ -0,0 +1,74 @@ +/* $OpenBSD: w_fork.c,v 1.1 2015/04/07 01:27:07 guenther Exp $ */ + +/* + * Copyright (c) 2008 Kurt Miller <kurt@openbsd.org> + * Copyright (c) 2008 Philip Guenther <guenther@openbsd.org> + * Copyright (c) 2003 Daniel Eischen <deischen@freebsd.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: /repoman/r/ncvs/src/lib/libc_r/uthread/uthread_atfork.c,v 1.1 2004/12/10 03:36:45 grog Exp $ + */ + +#include <unistd.h> +#include "thread_private.h" +#include "atfork.h" + +/* define and initialize the list */ +struct atfork_listhead _atfork_list = TAILQ_HEAD_INITIALIZER(_atfork_list); + +pid_t _thread_fork(void); + +pid_t +fork(void) +{ + struct atfork_fn *p; + pid_t newid; + + /* + * In the common case the list is empty; remain async-signal-safe + * then by skipping the locking and just forking + */ + if (TAILQ_FIRST(&_atfork_list) == NULL) + return (_thread_fork()); + + _ATFORK_LOCK(); + TAILQ_FOREACH_REVERSE(p, &_atfork_list, atfork_listhead, fn_next) + if (p->fn_prepare) + p->fn_prepare(); + + newid = _thread_fork(); + + if (newid == 0) { + TAILQ_FOREACH(p, &_atfork_list, fn_next) + if (p->fn_child) + p->fn_child(); + } else { + TAILQ_FOREACH(p, &_atfork_list, fn_next) + if (p->fn_parent) + p->fn_parent(); + } + _ATFORK_UNLOCK(); + + return (newid); +} diff --git a/lib/libc/thread/Makefile.inc b/lib/libc/thread/Makefile.inc index 248e6ede8cf..b5d3cb147dc 100644 --- a/lib/libc/thread/Makefile.inc +++ b/lib/libc/thread/Makefile.inc @@ -1,5 +1,5 @@ -# $OpenBSD: Makefile.inc,v 1.8 2014/07/16 20:02:17 okan Exp $ +# $OpenBSD: Makefile.inc,v 1.9 2015/04/07 01:27:07 guenther Exp $ .PATH: ${LIBCSRCDIR}/thread -SRCS+= unithread_malloc_lock.c unithread_mutex.c unithread_tag.c +SRCS+= unithread_malloc_lock.c unithread_mutex.c unithread_tag.c atfork.c diff --git a/lib/libc/thread/atfork.c b/lib/libc/thread/atfork.c new file mode 100644 index 00000000000..e4ae398df5a --- /dev/null +++ b/lib/libc/thread/atfork.c @@ -0,0 +1,56 @@ +/* $OpenBSD: atfork.c,v 1.1 2015/04/07 01:27:07 guenther Exp $ */ + +/* + * Copyright (c) 2008 Kurt Miller <kurt@openbsd.org> + * Copyright (c) 2008 Philip Guenther <guenther@openbsd.org> + * Copyright (c) 2003 Daniel Eischen <deischen@freebsd.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: /repoman/r/ncvs/src/lib/libc_r/uthread/uthread_atfork.c,v 1.1 2004/12/10 03:36:45 grog Exp $ + */ + +#include <errno.h> +#include <stdlib.h> + +#include "thread_private.h" +#include "atfork.h" + +int +_thread_atfork(void (*prepare)(void), void (*parent)(void), + void (*child)(void), void *dso) +{ + struct atfork_fn *af; + + if ((af = malloc(sizeof *af)) == NULL) + return (ENOMEM); + + af->fn_prepare = prepare; + af->fn_parent = parent; + af->fn_child = child; + af->fn_dso = dso; + _ATFORK_LOCK(); + TAILQ_INSERT_TAIL(&_atfork_list, af, fn_next); + _ATFORK_UNLOCK(); + return (0); +} diff --git a/lib/libc/thread/unithread_malloc_lock.c b/lib/libc/thread/unithread_malloc_lock.c index 920250139b8..d813bc708f2 100644 --- a/lib/libc/thread/unithread_malloc_lock.c +++ b/lib/libc/thread/unithread_malloc_lock.c @@ -1,4 +1,4 @@ -/* $OpenBSD: unithread_malloc_lock.c,v 1.8 2008/06/13 21:18:43 otto Exp $ */ +/* $OpenBSD: unithread_malloc_lock.c,v 1.9 2015/04/07 01:27:07 guenther Exp $ */ #include <sys/time.h> #include "thread_private.h" @@ -15,6 +15,12 @@ WEAK_PROTOTYPE(_thread_atexit_unlock); WEAK_ALIAS(_thread_atexit_lock); WEAK_ALIAS(_thread_atexit_unlock); +WEAK_PROTOTYPE(_thread_atfork_lock); +WEAK_PROTOTYPE(_thread_atfork_unlock); + +WEAK_ALIAS(_thread_atfork_lock); +WEAK_ALIAS(_thread_atfork_unlock); + WEAK_PROTOTYPE(_thread_arc4_lock); WEAK_PROTOTYPE(_thread_arc4_unlock); @@ -46,6 +52,18 @@ WEAK_NAME(_thread_atexit_unlock)(void) } void +WEAK_NAME(_thread_atfork_lock)(void) +{ + return; +} + +void +WEAK_NAME(_thread_atfork_unlock)(void) +{ + return; +} + +void WEAK_NAME(_thread_arc4_lock)(void) { return; diff --git a/lib/librthread/rthread.c b/lib/librthread/rthread.c index 632308ef5db..688f438a27b 100644 --- a/lib/librthread/rthread.c +++ b/lib/librthread/rthread.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rthread.c,v 1.79 2014/11/16 05:26:20 guenther Exp $ */ +/* $OpenBSD: rthread.c,v 1.80 2015/04/07 01:27:07 guenther Exp $ */ /* * Copyright (c) 2004,2005 Ted Unangst <tedu@openbsd.org> * All Rights Reserved. @@ -736,6 +736,8 @@ static void *__libc_overrides[] __used = { &_thread_arc4_unlock, &_thread_atexit_lock, &_thread_atexit_unlock, + &_thread_atfork_lock, + &_thread_atfork_unlock, &_thread_malloc_lock, &_thread_malloc_unlock, &_thread_mutex_destroy, diff --git a/lib/librthread/rthread_fork.c b/lib/librthread/rthread_fork.c index cb76421d2a1..c9086daf595 100644 --- a/lib/librthread/rthread_fork.c +++ b/lib/librthread/rthread_fork.c @@ -1,8 +1,8 @@ -/* $OpenBSD: rthread_fork.c,v 1.10 2013/11/29 16:27:40 guenther Exp $ */ +/* $OpenBSD: rthread_fork.c,v 1.11 2015/04/07 01:27:07 guenther Exp $ */ /* * Copyright (c) 2008 Kurt Miller <kurt@openbsd.org> - * Copyright (c) 2008 Philip Guenther <guenther@gmail.com> + * Copyright (c) 2008 Philip Guenther <guenther@openbsd.org> * Copyright (c) 2003 Daniel Eischen <deischen@freebsd.org> * All rights reserved. * @@ -46,18 +46,6 @@ #include "rthread.h" -struct rthread_atfork { - TAILQ_ENTRY(rthread_atfork) next; - void (*prepare)(void); - void (*parent)(void); - void (*child)(void); -}; - -static TAILQ_HEAD(atfork_listhead, rthread_atfork) _atfork_list = - TAILQ_HEAD_INITIALIZER(_atfork_list); - -static struct _spinlock _atfork_lock = _SPINLOCK_UNLOCKED; - pid_t _thread_sys_fork(void); pid_t _thread_sys_vfork(void); pid_t _dofork(int); @@ -144,27 +132,9 @@ _dofork(int is_vfork) } pid_t -fork(void) +_thread_fork(void) { - struct rthread_atfork *p; - pid_t newid; - - _spinlock(&_atfork_lock); - TAILQ_FOREACH_REVERSE(p, &_atfork_list, atfork_listhead, next) - if (p->prepare) - p->prepare(); - newid = _dofork(0); - if (newid == 0) { - TAILQ_FOREACH(p, &_atfork_list, next) - if (p->child) - p->child(); - } else { - TAILQ_FOREACH(p, &_atfork_list, next) - if (p->parent) - p->parent(); - } - _spinunlock(&_atfork_lock); - return newid; + return _dofork(0); } pid_t @@ -172,21 +142,3 @@ vfork(void) { return _dofork(1); } - -int -pthread_atfork(void (*prepare)(void), void (*parent)(void), - void (*child)(void)) -{ - struct rthread_atfork *af; - - if ((af = malloc(sizeof *af)) == NULL) - return (ENOMEM); - - af->prepare = prepare; - af->parent = parent; - af->child = child; - _spinlock(&_atfork_lock); - TAILQ_INSERT_TAIL(&_atfork_list, af, next); - _spinunlock(&_atfork_lock); - return (0); -} diff --git a/lib/librthread/rthread_libc.c b/lib/librthread/rthread_libc.c index 13df27c498e..018368a84dd 100644 --- a/lib/librthread/rthread_libc.c +++ b/lib/librthread/rthread_libc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rthread_libc.c,v 1.11 2013/06/01 20:47:40 tedu Exp $ */ +/* $OpenBSD: rthread_libc.c,v 1.12 2015/04/07 01:27:07 guenther Exp $ */ /* $snafu: libc_tag.c,v 1.4 2004/11/30 07:00:06 marc Exp $ */ /* PUBLIC DOMAIN: No Rights Reserved. Marco S Hyman <marc@snafu.org> */ @@ -184,6 +184,23 @@ _thread_atexit_unlock(void) } /* + * atfork lock + */ +static struct _spinlock atfork_lock = _SPINLOCK_UNLOCKED; + +void +_thread_atfork_lock(void) +{ + _spinlock(&atfork_lock); +} + +void +_thread_atfork_unlock(void) +{ + _spinunlock(&atfork_lock); +} + +/* * arc4random lock */ static struct _spinlock arc4_lock = _SPINLOCK_UNLOCKED; diff --git a/lib/librthread/shlib_version b/lib/librthread/shlib_version index 7c92aff4893..0aab0406bf8 100644 --- a/lib/librthread/shlib_version +++ b/lib/librthread/shlib_version @@ -1,2 +1,2 @@ -major=18 -minor=1 +major=19 +minor=0 diff --git a/regress/lib/csu/callbacks/Makefile b/regress/lib/csu/callbacks/Makefile index 48474134a56..b74854fb45c 100644 --- a/regress/lib/csu/callbacks/Makefile +++ b/regress/lib/csu/callbacks/Makefile @@ -1,7 +1,6 @@ -# $OpenBSD: Makefile,v 1.1 2014/11/23 08:46:49 guenther Exp $ +# $OpenBSD: Makefile,v 1.2 2015/04/07 01:27:07 guenther Exp $ -SUBDIR+= libaa libab atexit -# not yet: pthread_atfork +SUBDIR+= libaa libab atexit pthread_atfork install: diff --git a/regress/lib/csu/callbacks/pthread_atfork/Makefile b/regress/lib/csu/callbacks/pthread_atfork/Makefile index 8e685447d7b..ecefb366a9b 100644 --- a/regress/lib/csu/callbacks/pthread_atfork/Makefile +++ b/regress/lib/csu/callbacks/pthread_atfork/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.1 2014/11/23 08:46:49 guenther Exp $ +# $OpenBSD: Makefile,v 1.2 2015/04/07 01:27:07 guenther Exp $ .include <bsd.obj.mk> @@ -31,7 +31,7 @@ NOMAN= CLEANFILES= parent_out child_out -TESTS= 0 +TESTS= 0 1 2 3 regress-pthread_atfork: ${PROG} for i in ${TESTS}; do \ diff --git a/regress/lib/csu/callbacks/pthread_atfork/expected_child.out b/regress/lib/csu/callbacks/pthread_atfork/expected_child.out new file mode 100644 index 00000000000..345d837c844 --- /dev/null +++ b/regress/lib/csu/callbacks/pthread_atfork/expected_child.out @@ -0,0 +1,20 @@ +testp atfork1_child +libaa atfork_child +testp atfork2_child +libab atfork_child +testp atfork3_child +finished 0 + +testp atfork1_child +testp atfork2_child +testp atfork3_child +finished 1 + +testp atfork1_child +testp atfork3_child +finished 2 + +testp atfork1_child +testp atfork2_child +finished 3 + diff --git a/regress/lib/csu/callbacks/pthread_atfork/expected_parent.out b/regress/lib/csu/callbacks/pthread_atfork/expected_parent.out new file mode 100644 index 00000000000..18cdc22e663 --- /dev/null +++ b/regress/lib/csu/callbacks/pthread_atfork/expected_parent.out @@ -0,0 +1,37 @@ +testp atfork3_prepare +libab atfork_prepare +testp atfork2_prepare +libaa atfork_prepare +testp atfork1_prepare +testp atfork1_parent +libaa atfork_parent +testp atfork2_parent +libab atfork_parent +testp atfork3_parent +finished 0 + +testp atfork3_prepare +testp atfork2_prepare +testp atfork1_prepare +testp atfork1_parent +testp atfork2_parent +testp atfork3_parent +finished 1 + +testp atfork3_prepare +libab atfork_prepare +exe atfork_dlclose begin +exe atfork_dlclose end +testp atfork1_prepare +testp atfork1_parent +testp atfork3_parent +finished 2 + +exe atfork_dlclose begin +exe atfork_dlclose end +testp atfork2_prepare +testp atfork1_prepare +testp atfork1_parent +testp atfork2_parent +finished 3 + diff --git a/regress/lib/csu/callbacks/pthread_atfork/pthread_atfork_test.c b/regress/lib/csu/callbacks/pthread_atfork/pthread_atfork_test.c index c6a93a0e080..225e5f1f1af 100644 --- a/regress/lib/csu/callbacks/pthread_atfork/pthread_atfork_test.c +++ b/regress/lib/csu/callbacks/pthread_atfork/pthread_atfork_test.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pthread_atfork_test.c,v 1.1 2014/11/23 08:46:49 guenther Exp $ */ +/* $OpenBSD: pthread_atfork_test.c,v 1.2 2015/04/07 01:27:07 guenther Exp $ */ /* * Copyright (c) 2014 Philip Guenther <guenther@openbsd.org> @@ -16,6 +16,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include <sys/wait.h> #include <dlfcn.h> #include <err.h> #include <pthread.h> @@ -86,7 +87,7 @@ int main(int argc, char **argv) { pid_t pid; - int test; + int test, status; otherf = fdopen(3, "w"); if (otherf == NULL) @@ -150,5 +151,6 @@ main(int argc, char **argv) fflush(otherf); pid = fork(); + waitpid(pid, &status, 0); return (0); } |