This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] Call exit directly in clone (BZ #21512)


On 06/23/2017 08:37 AM, Adhemerval Zanella wrote:
> On aarch64, alpha, arm, hppa, mips, nios2, powerpc, s390, sh,
> sparch, tile, and x86_64 the clone syscall jumps to _exit after
> the child execution and the function ends the process execution by
> calling exit_group.  This behavior have a small issue where
> threads created with CLONE_THREAD using clone syscall directly
> will eventually exit the whole group altogether instead of just
> the thread created.  Also, microblaze, ia64, i386, and m68k
> differs by calling exit syscall directly.
> 
> This patch changes all architectures to call the exit syscall
> directly, as for microblaze, ia64, i386, and m68k.  This do not
> have change glibc internal behavior in any sort, since the only
> usage of clone implementation in posix_spawn calls _exit directly
> in the created child (fork uses a direct call to clone).
> 
> Checked on x86_64-linux-gnu, i686-linux-gnu, aarch64-linux-gnu,
> powerpc-linux-gnu, powerpc64le-linux-gnu, sparc64-linux-gnu,
> and sparcv9-linux-gnu.

How is it that this doesn't break threading completely on the existing
architectures that call _exit? Is it because NPTL calls the clone syscall
directly instead of calling the clone() function and nobody uses clone()
because of all the other problems it has?

I admit that only an explicit call to _exit() or exit() should terminate
every thread in the thread group, *and* looking at the kernel side code
I see it does try to terminate every thread in the group (zap_other_threads()).

The patch looks good to me, but I just want some clarification about my
question "Why haven't we noticed?" :-)

> 	[BZ #21512]
> 	* sysdeps/unix/sysv/linux/aarch64/clone.S (__clone): Call exit
> 	syscall instead of jump to _exit.
> 	(CLONE_VM_BIT): Remove unused define.
> 	(CLONE_VM): Likewise.
> 	(CLONE_THREAD_BIT): Likewise.
> 	(CLONE_THREAD): Likewise.
> 	* sysdeps/unix/sysv/linux/alpha/clone.S (__clone): Likewise.
> 	(CLONE_VM): Remove unused define.
> 	* sysdeps/unix/sysv/linux/arm/clone.S (__clone): Likewise.
> 	(CLONE_VM): Remove unused define.
> 	(CLONE_THREAD): Likewise.
> 	* sysdeps/unix/sysv/linux/i386/clone.S (CLONE_VM): Likewise.
> 	* sysdeps/unix/sysv/linux/ia64/clone2.S (__clone2): Call exit
> 	syscall instead of jump to _exit.
> 	* sysdeps/unix/sysv/linux/hppa/clone.S (__clone): Likewise.
> 	* sysdeps/unix/sysv/linux/mips/clone.S (__clone): Likewise.
> 	(CLONE_VM): Remove unused define.
> 	(CLONE_THREAD): Likewise.
> 	* sysdeps/unix/sysv/linux/nios2/clone.S (__clone): Likewise.
> 	(CLONE_VM): Remove unused define.
> 	* sysdeps/unix/sysv/linux/powerpc/powerpc32/clone.S (__clone):
> 	Likewise.
> 	(CLONE_VM): Remove unused define.
> 	(CLONE_THREAD): Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S (__clone):
> 	Likewise.
> 	(CLONE_VM): Remove unused define.
> 	(CLONE_THREAD): Likewise.
> 	* sysdeps/unix/sysv/linux/s390/s390-32/clone.S (__clone): Likewise.
> 	* sysdeps/unix/sysv/linux/s390/s390-64/clone.S (__clone): Likewise.
> 	* sysdeps/unix/sysv/linux/sh/clone.S  (__clone): Likewise.
> 	* sysdeps/unix/sysv/linux/sparc/sparc32/clone.S (__clone): Likewise.
> 	(CLONE_VM): Remove unused define.
> 	* sysdeps/unix/sysv/linux/sparc/sparc64/clone.S (__clone): Likewise.
> 	(CLONE_VM): Remove unused define.
> 	* sysdeps/unix/sysv/linux/tile/clone.S (__clone): Likewise.
> 	* sysdeps/unix/sysv/linux/x86_64/clone.S (__clone): Likewise.
> 	(CLONE_VM): Remove unused define.
> 	* sysdeps/unix/sysv/linux/Makefile (tests): Add tst-clone3.
> 	* sysdeps/unix/sysv/linux/tst-clone3.c: New file.
> ---
>  sysdeps/unix/sysv/linux/Makefile                  |  4 +-
>  sysdeps/unix/sysv/linux/aarch64/clone.S           |  9 +--
>  sysdeps/unix/sysv/linux/alpha/clone.S             | 11 +--
>  sysdeps/unix/sysv/linux/arm/clone.S               |  6 +-
>  sysdeps/unix/sysv/linux/hppa/clone.S              |  6 +-
>  sysdeps/unix/sysv/linux/i386/clone.S              |  2 -
>  sysdeps/unix/sysv/linux/ia64/clone2.S             |  8 +-
>  sysdeps/unix/sysv/linux/m68k/clone.S              |  2 -
>  sysdeps/unix/sysv/linux/mips/clone.S              | 12 +--
>  sysdeps/unix/sysv/linux/nios2/clone.S             | 17 +---
>  sysdeps/unix/sysv/linux/powerpc/powerpc32/clone.S |  7 +-
>  sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S | 11 +--
>  sysdeps/unix/sysv/linux/s390/s390-32/clone.S      |  2 +-
>  sysdeps/unix/sysv/linux/s390/s390-64/clone.S      |  2 +-
>  sysdeps/unix/sysv/linux/sh/clone.S                | 21 +----
>  sysdeps/unix/sysv/linux/sparc/sparc32/clone.S     |  5 +-
>  sysdeps/unix/sysv/linux/sparc/sparc64/clone.S     |  5 +-
>  sysdeps/unix/sysv/linux/tile/clone.S              |  6 +-
>  sysdeps/unix/sysv/linux/tst-clone3.c              | 95 +++++++++++++++++++++++
>  sysdeps/unix/sysv/linux/x86_64/clone.S            |  5 +-
>  20 files changed, 130 insertions(+), 106 deletions(-)
>  create mode 100644 sysdeps/unix/sysv/linux/tst-clone3.c
> 
> diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
> index 8b340d4..9d6a2de 100644
> --- a/sysdeps/unix/sysv/linux/Makefile
> +++ b/sysdeps/unix/sysv/linux/Makefile
> @@ -49,8 +49,8 @@ sysdep_headers += sys/mount.h sys/acct.h sys/sysctl.h \
>  		  bits/mman-linux.h \
>  		  bits/siginfo-arch.h bits/siginfo-consts-arch.h
>  
> -tests += tst-clone tst-clone2 tst-fanotify tst-personality tst-quota \
> -	 tst-sync_file_range test-errno-linux
> +tests += tst-clone tst-clone2 tst-clone3 tst-fanotify tst-personality \
> +	 tst-quota tst-sync_file_range test-errno-linux
>  
>  # Generate the list of SYS_* macros for the system calls (__NR_* macros).
>  
> diff --git a/sysdeps/unix/sysv/linux/aarch64/clone.S b/sysdeps/unix/sysv/linux/aarch64/clone.S
> index 259ec07..905915a 100644
> --- a/sysdeps/unix/sysv/linux/aarch64/clone.S
> +++ b/sysdeps/unix/sysv/linux/aarch64/clone.S
> @@ -23,12 +23,6 @@
>  #define _ERRNO_H	1
>  #include <bits/errno.h>
>  
> -#define CLONE_VM_BIT      8
> -#define CLONE_VM          (1 << CLONE_VM_BIT)
> -
> -#define CLONE_THREAD_BIT  16
> -#define CLONE_THREAD      (1 << CLONE_THREAD_BIT)
> -
>  /* int clone(int (*fn)(void *arg),            x0
>  	     void *child_stack,               x1
>  	     int flags,                       x2
> @@ -84,7 +78,8 @@ thread_start:
>  	blr	x10
>  
>  	/* We are done, pass the return value through x0.  */
> -	b	HIDDEN_JUMPTARGET(_exit)
> +	mov	x8, #SYS_ify(exit)
> +	svc	0x0
>  	cfi_endproc
>  	.size thread_start, .-thread_start
>  
> diff --git a/sysdeps/unix/sysv/linux/alpha/clone.S b/sysdeps/unix/sysv/linux/alpha/clone.S
> index 20ae361..550461f 100644
> --- a/sysdeps/unix/sysv/linux/alpha/clone.S
> +++ b/sysdeps/unix/sysv/linux/alpha/clone.S
> @@ -23,8 +23,6 @@
>  #define _ERRNO_H	1
>  #include <bits/errno.h>
>  
> -#define CLONE_VM	0x00000100
> -
>  /* int clone(int (*fn)(void *arg), void *child_stack, int flags,
>  	     void *arg, pid_t *ptid, void *tls, pid_t *ctid);
>  
> @@ -100,13 +98,8 @@ thread_start:
>  	jsr	ra, (pv)
>  	ldgp	gp, 0(ra)
>  
> -	/* Call _exit rather than doing it inline for breakpoint purposes.  */
> -	mov	v0, a0
> -#ifdef PIC
> -	bsr	ra, HIDDEN_JUMPTARGET(_exit)	!samegp
> -#else
> -	jsr	ra, HIDDEN_JUMPTARGET(_exit)
> -#endif
> +	ldiq	v0, __NR_exit
> +	call_pal PAL_callsys
>  
>  	/* Die horribly.  */
>  	.align	4
> diff --git a/sysdeps/unix/sysv/linux/arm/clone.S b/sysdeps/unix/sysv/linux/arm/clone.S
> index a309add..f01968a 100644
> --- a/sysdeps/unix/sysv/linux/arm/clone.S
> +++ b/sysdeps/unix/sysv/linux/arm/clone.S
> @@ -24,9 +24,6 @@
>  #define _ERRNO_H	1
>  #include <bits/errno.h>
>  
> -#define CLONE_VM      0x00000100
> -#define CLONE_THREAD  0x00010000
> -
>  /* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
>  	     pid_t *ptid, struct user_desc *tls, pid_t *ctid); */
>  
> @@ -76,7 +73,8 @@ PSEUDO_END (__clone)
>  	BLX (ip)
>  
>  	@ and we are done, passing the return value through r0
> -	b	PLTJMP(HIDDEN_JUMPTARGET(_exit))
> +	ldr	r7, =SYS_ify(clone)
> +	swi	0x0
>  
>  	.fnend
>  
> diff --git a/sysdeps/unix/sysv/linux/hppa/clone.S b/sysdeps/unix/sysv/linux/hppa/clone.S
> index d36b302..8c43944 100644
> --- a/sysdeps/unix/sysv/linux/hppa/clone.S
> +++ b/sysdeps/unix/sysv/linux/hppa/clone.S
> @@ -148,10 +148,10 @@ ENTRY(__clone)
>  	copy	%r4, %r19
>  #endif
>  	/* The call to _exit needs saved r19.  */
> -	bl	_exit, %rp
> -	copy	%ret0, %arg0
> +	ble     0x100(%sr2, %r0)
> +	ldi	__NR_exit, %r20
>  
> -	/* We should not return from _exit.
> +	/* We should not return from exit.
>             We do not restore r4, or the stack state.  */
>  	iitlbp	%r0, (%sr0, %r0)
>  
> diff --git a/sysdeps/unix/sysv/linux/i386/clone.S b/sysdeps/unix/sysv/linux/i386/clone.S
> index a4ba3e2..49c82d9 100644
> --- a/sysdeps/unix/sysv/linux/i386/clone.S
> +++ b/sysdeps/unix/sysv/linux/i386/clone.S
> @@ -39,8 +39,6 @@
>  #define __NR_clone 120
>  #define SYS_clone 120
>  
> -#define CLONE_VM	0x00000100
> -
>          .text
>  ENTRY (__clone)
>  	/* Sanity check arguments.  */
> diff --git a/sysdeps/unix/sysv/linux/ia64/clone2.S b/sysdeps/unix/sysv/linux/ia64/clone2.S
> index 9b59473..3157ce9 100644
> --- a/sysdeps/unix/sysv/linux/ia64/clone2.S
> +++ b/sysdeps/unix/sysv/linux/ia64/clone2.S
> @@ -74,11 +74,11 @@ ENTRY(__clone2)
>  	mov b6=out1
>  	br.call.dptk.many rp=b6	/* Call fn(arg) in the child 	*/
>  	;;
> -	mov out0=r8		/* Argument to _exit		*/
> +	mov out0=r8		/* Argument to exit		*/
>  	mov gp=loc0
> -	.globl HIDDEN_JUMPTARGET(_exit)
> -	br.call.dpnt.many rp=HIDDEN_JUMPTARGET(_exit)
> -				/* call _exit with result from fn.	*/
> +	mov r15=SYS_ify (exit)
> +	.save rp, r0
> +	break __BREAK_SYSCALL
>  	ret			/* Not reached.		*/
>  PSEUDO_END(__clone2)
>  
> diff --git a/sysdeps/unix/sysv/linux/m68k/clone.S b/sysdeps/unix/sysv/linux/m68k/clone.S
> index a680191..0894b2a 100644
> --- a/sysdeps/unix/sysv/linux/m68k/clone.S
> +++ b/sysdeps/unix/sysv/linux/m68k/clone.S
> @@ -24,8 +24,6 @@
>  #include <bits/errno.h>
>  #include <tls.h>
>  
> -#define CLONE_VM      0x00000100
> -
>  /* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
>  	     void *parent_tidptr, void *tls, void *child_tidptr) */
>  
> diff --git a/sysdeps/unix/sysv/linux/mips/clone.S b/sysdeps/unix/sysv/linux/mips/clone.S
> index 8b79457..855f972 100644
> --- a/sysdeps/unix/sysv/linux/mips/clone.S
> +++ b/sysdeps/unix/sysv/linux/mips/clone.S
> @@ -25,9 +25,6 @@
>  #include <bits/errno.h>
>  #include <tls.h>
>  
> -#define CLONE_VM      0x00000100
> -#define CLONE_THREAD  0x00010000
> -
>  /* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
>  	     void *parent_tidptr, void *tls, void *child_tidptr) */
>  
> @@ -137,14 +134,9 @@ L(thread_start):
>  	/* Call the user's function.  */
>  	jal		t9
>  
> -	/* Call _exit rather than doing it inline for breakpoint purposes.  */
>  	move		a0,v0
> -#ifdef __PIC__
> -	PTR_LA		t9,_exit
> -	jalr		t9
> -#else
> -	jal		_exit
> -#endif
> +	li		v0,__NR_clone
> +	syscall
>  
>  	END(__thread_start)
>  
> diff --git a/sysdeps/unix/sysv/linux/nios2/clone.S b/sysdeps/unix/sysv/linux/nios2/clone.S
> index 7929dfa..2ba8258 100644
> --- a/sysdeps/unix/sysv/linux/nios2/clone.S
> +++ b/sysdeps/unix/sysv/linux/nios2/clone.S
> @@ -25,8 +25,6 @@
>  #include <bits/errno.h>
>  #include <tcb-offsets.h>
>  
> -#define CLONE_VM      0x00000100
> -
>  /* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
>  	     void *parent_tidptr, void *tls, void *child_tidptr) */
>  
> @@ -75,18 +73,9 @@ thread_start:
>          /* Call the user's function.  */
>  	callr	r5
>  
> -	/* _exit with the result.  */
> -	mov	r4, r2
> -#ifdef PIC
> -	nextpc	r22
> -1:	movhi	r8, %hiadj(_gp_got - 1b)
> -	addi	r8, r8, %lo(_gp_got - 1b)
> -	add	r22, r22, r8
> -	ldw	r8, %call(HIDDEN_JUMPTARGET(_exit))(r22)
> -	jmp	r8
> -#else
> -	jmpi	_exit
> -#endif
> +	/* exit with the result.  */
> +	movi	r2, SYS_ify (exit)
> +	trap
>  	cfi_endproc
>  
>  	cfi_startproc
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/clone.S b/sysdeps/unix/sysv/linux/powerpc/powerpc32/clone.S
> index a07b7d3..e48cc5f 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/clone.S
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/clone.S
> @@ -20,10 +20,6 @@
>  #define _ERRNO_H	1
>  #include <bits/errno.h>
>  
> -#define CLONE_VM	0x00000100
> -#define CLONE_THREAD	0x00010000
> -
> -
>  /* This is the only really unusual system call in PPC linux, but not
>     because of any weirdness in the system call itself; because of
>     all the freaky stuff we have to do to make the call useful.  */
> @@ -80,8 +76,7 @@ ENTRY (__clone)
>  	mtctr	r30
>  	mr	r3,r31
>  	bctrl
> -	/* Call _exit with result from procedure.  */
> -	b	HIDDEN_JUMPTARGET(_exit)
> +	DO_CALL(SYS_ify(exit))
>  
>  L(parent):
>  	/* Parent.  Restore registers & return.  */
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S b/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S
> index 9e5bfd2..78c353a 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S
> @@ -20,9 +20,6 @@
>  #define _ERRNO_H	1
>  #include <bits/errno.h>
>  
> -#define CLONE_VM	0x00000100
> -#define CLONE_THREAD	0x00010000
> -
>  /* This is the only really unusual system call in PPC linux, but not
>     because of any weirdness in the system call itself; because of
>     all the freaky stuff we have to do to make the call useful.  */
> @@ -84,15 +81,11 @@ ENTRY (__clone)
>  	mr	r3,r31
>  	bctrl
>  	ld	r2,FRAME_TOC_SAVE(r1)
> -	/* Call _exit with result from procedure.  */
> -#ifdef SHARED
> -	b	JUMPTARGET(__GI__exit)
> -#else
> -	bl	JUMPTARGET(_exit)
> +
> +	DO_CALL(SYS_ify(exit))
>  	/* We won't ever get here but provide a nop so that the linker
>  	   will insert a toc adjusting stub if necessary.  */
>  	nop
> -#endif
>  
>  L(badargs):
>  	cfi_startproc
> diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/clone.S b/sysdeps/unix/sysv/linux/s390/s390-32/clone.S
> index a8b4dbc..1588e5f 100644
> --- a/sysdeps/unix/sysv/linux/s390/s390-32/clone.S
> +++ b/sysdeps/unix/sysv/linux/s390/s390-32/clone.S
> @@ -59,7 +59,7 @@ thread_start:
>  	ahi     %r15,-96        /* make room on the stack for the save area */
>  	xc	0(4,%r15),0(%r15)
>  	basr    %r14,%r1        /* jump to fn */
> -	DO_CALL (exit, 1)
> +	svc	SYS_ify(exit)
>  
>  libc_hidden_def (__clone)
>  weak_alias (__clone, clone)
> diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/clone.S b/sysdeps/unix/sysv/linux/s390/s390-64/clone.S
> index daf8a58..5843188 100644
> --- a/sysdeps/unix/sysv/linux/s390/s390-64/clone.S
> +++ b/sysdeps/unix/sysv/linux/s390/s390-64/clone.S
> @@ -60,7 +60,7 @@ thread_start:
>  	aghi	%r15,-160	/* make room on the stack for the save area */
>  	xc	0(8,%r15),0(%r15)
>  	basr	%r14,%r1	/* jump to fn */
> -	DO_CALL	(exit, 1)
> +	svc	SYS_ify(exit)
>  
>  libc_hidden_def (__clone)
>  weak_alias (__clone, clone)
> diff --git a/sysdeps/unix/sysv/linux/sh/clone.S b/sysdeps/unix/sysv/linux/sh/clone.S
> index 9063b21..b13a64b 100644
> --- a/sysdeps/unix/sysv/linux/sh/clone.S
> +++ b/sysdeps/unix/sysv/linux/sh/clone.S
> @@ -73,25 +73,8 @@ ENTRY(__clone)
>  	 mov.l	@(4,r15), r4
>  
>  	/* we are done, passing the return value through r0  */
> -	mov.l	.L3, r1
> -#ifdef SHARED
> -	mov.l	r12, @-r15
> -	sts.l	pr, @-r15
> -	mov	r0, r4
> -	mova	.LG, r0
> -	mov.l	.LG, r12
> -	add	r0, r12
> -	mova	.L3, r0
> -	add	r0, r1
> -	jsr	@r1
> -	 nop
> -	lds.l	@r15+, pr
> -	rts
> -	 mov.l	@r15+, r12
> -#else
> -	jmp	@r1
> -	 mov	r0, r4
> -#endif
> +	mov	#+SYS_ify(exit), r3
> +	trapa	#0x15
>  	.align	2
>  .LG:
>  	.long	_GLOBAL_OFFSET_TABLE_
> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/clone.S b/sysdeps/unix/sysv/linux/sparc/sparc32/clone.S
> index 6d2f5bd..1afa26e 100644
> --- a/sysdeps/unix/sysv/linux/sparc/sparc32/clone.S
> +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/clone.S
> @@ -24,8 +24,6 @@
>  #include <tcb-offsets.h>
>  #include <sysdep.h>
>  
> -#define CLONE_VM	0x00000100
> -
>  /* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
>  	     pid_t *ptid, void *tls, pid_t *ctid); */
>  
> @@ -81,7 +79,8 @@ __thread_start:
>  	mov	%g0, %fp	/* terminate backtrace */
>  	call	%g2
>  	 mov	%g3,%o0
> -	call	HIDDEN_JUMPTARGET(_exit),0
> +	set	__NR_exit, %g1
> +	ta	0x10
>  	 nop
>  
>  	.size	__thread_start, .-__thread_start
> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/clone.S b/sysdeps/unix/sysv/linux/sparc/sparc64/clone.S
> index fc28539..785ccd1 100644
> --- a/sysdeps/unix/sysv/linux/sparc/sparc64/clone.S
> +++ b/sysdeps/unix/sysv/linux/sparc/sparc64/clone.S
> @@ -24,8 +24,6 @@
>  #include <tcb-offsets.h>
>  #include <sysdep.h>
>  
> -#define CLONE_VM	0x00000100
> -
>  /* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
>  	     pid_t *ptid, void *tls, pid_t *ctid); */
>  
> @@ -78,7 +76,8 @@ __thread_start:
>  	mov	%g0, %fp	/* terminate backtrace */
>  	call	%g2
>  	 mov	%g3,%o0
> -	call	HIDDEN_JUMPTARGET(_exit),0
> +	set	__NR_exit, %g1
> +	ta	0x6d
>  	 nop
>  
>  	.size	__thread_start, .-__thread_start
> diff --git a/sysdeps/unix/sysv/linux/tile/clone.S b/sysdeps/unix/sysv/linux/tile/clone.S
> index d7d2a3b..9610acd 100644
> --- a/sysdeps/unix/sysv/linux/tile/clone.S
> +++ b/sysdeps/unix/sysv/linux/tile/clone.S
> @@ -168,10 +168,8 @@ ENTRY (__clone)
>  	 move r0, r31
>  	 jalr r32
>  	}
> -	{
> -	 j HIDDEN_JUMPTARGET(_exit)
> -	 info INFO_OP_CANNOT_BACKTRACE   /* Notify backtracer to stop. */
> -	}
> +	moveli TREG_SYSCALL_NR_NAME, __NR_exit
> +	swint1
>  PSEUDO_END (__clone)
>  
>  libc_hidden_def (__clone)
> diff --git a/sysdeps/unix/sysv/linux/tst-clone3.c b/sysdeps/unix/sysv/linux/tst-clone3.c
> new file mode 100644
> index 0000000..e893e4d
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/tst-clone3.c
> @@ -0,0 +1,95 @@
> +/* Check if clone (CLONE_THREAD) does not call exit_group (BZ #21512)
> +   Copyright (C) 2017 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 <string.h>
> +#include <sched.h>
> +#include <signal.h>
> +#include <unistd.h>
> +#include <sys/syscall.h>
> +#include <sys/wait.h>
> +#include <sys/types.h>
> +#include <linux/futex.h>
> +
> +#include <stackinfo.h>  /* For _STACK_GROWS_{UP,DOWN}.  */
> +#include <support/check.h>
> +
> +/* Test if clone call with CLONE_THREAD does not call exit_group.  The 'f'
> +   function returns '1', which will be used by clone thread to call the
> +   'exit' syscall directly.  If _exit is used instead, exit_group will be
> +   used and thus the thread group will finish with return value of '1'
> +   (where '2' from main thread is expected.  */

s/(where/where/g

> +
> +static int
> +f (void *a)
> +{
> +  return 1;
> +}
> +
> +/* Futex wait for TID argument, similar to pthread_join internal
> +   implementation.  */
> +#define wait_tid(tid) \
> +  do {					\
> +    __typeof (tid) __tid;		\
> +    while ((__tid = (tid)) != 0)	\
> +      futex_wait (&(tid), __tid);	\
> +  } while (0)
> +
> +static inline int
> +futex_wait (int *futexp, int val)
> +{
> +  return syscall (__NR_futex, futexp, FUTEX_WAIT, val);
> +}
> +
> +static int
> +do_test (void)
> +{
> +  char st[1024] __attribute__ ((aligned));
> +  int clone_flags = CLONE_THREAD;
> +  /* Minimum required flags to used along with CLONE_THREAD.  */
> +  clone_flags |= CLONE_VM | CLONE_SIGHAND;
> +  /* We will used ctid to call on futex to wait for thread exit.  */
> +  clone_flags |= CLONE_CHILD_CLEARTID;
> +  pid_t ctid, tid;
> +
> +#ifdef __ia64__
> +  extern int __clone2 (int (*__fn) (void *__arg), void *__child_stack_base,
> +		       size_t __child_stack_size, int __flags,
> +		       void *__arg, ...);
> +  tid = __clone2 (f, st, sizeof (st), clone_flags, NULL, /* ptid */ NULL,
> +		  /* tls */ NULL, &ctid);
> +#else
> +#if _STACK_GROWS_DOWN
> +  tid = clone (f, st + sizeof (st), clone_flags, NULL, /* ptid */ NULL,
> +	       /* tls */ NULL, &ctid);
> +#elif _STACK_GROWS_UP
> +  tid = clone (f, st, clone_flags, NULL, /* ptid */ NULL, /* tls */ NULL,
> +	       &ctid);
> +#else
> +#error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP"
> +#endif
> +#endif
> +  if (tid == -1)
> +    FAIL_EXIT1 ("clone failed: %m");
> +
> +  wait_tid (ctid);
> +
> +  return 2;
> +}
> +
> +#define EXPECTED_STATUS 2
> +#include <support/test-driver.c>
> diff --git a/sysdeps/unix/sysv/linux/x86_64/clone.S b/sysdeps/unix/sysv/linux/x86_64/clone.S
> index d5c2d07..b10fc29 100644
> --- a/sysdeps/unix/sysv/linux/x86_64/clone.S
> +++ b/sysdeps/unix/sysv/linux/x86_64/clone.S
> @@ -23,8 +23,6 @@
>  #include <bits/errno.h>
>  #include <asm-syntax.h>
>  
> -#define CLONE_VM	0x00000100
> -
>  /* The userland implementation is:
>     int clone (int (*fn)(void *arg), void *child_stack, int flags, void *arg),
>     the kernel entry is:
> @@ -97,7 +95,8 @@ L(thread_start):
>  	call	*%rax
>  	/* Call exit with return value from function call. */
>  	movq	%rax, %rdi
> -	call	HIDDEN_JUMPTARGET (_exit)
> +	movl	$SYS_ify(exit), %eax
> +	syscall
>  	cfi_endproc;
>  
>  	cfi_startproc;
> 


-- 
Cheers,
Carlos.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]