mirror of
https://sourceware.org/git/glibc.git
synced 2025-01-05 01:00:14 +00:00
Call exit directly in clone (BZ #21512)
On aarch64, alpha, arm, hppa, mips, nios2, powerpc, sh, sparc, 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, s390, microblaze, ia64, i386, and m68k differs by calling exit syscall directly. This patch changes all architectures to call the exit syscall directly, as for s390, 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. [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/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. Fix
This commit is contained in:
parent
f819dbea0a
commit
3f823e87cc
42
ChangeLog
42
ChangeLog
@ -1,3 +1,45 @@
|
|||||||
|
2017-06-26 Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||||
|
|
||||||
|
[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/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.
|
||||||
|
|
||||||
2017-06-26 Paul E. Murphy <murphyp@linux.vnet.ibm.com>
|
2017-06-26 Paul E. Murphy <murphyp@linux.vnet.ibm.com>
|
||||||
Gabriel F. T. Gomes <gftg@linux.vnet.ibm.com>
|
Gabriel F. T. Gomes <gftg@linux.vnet.ibm.com>
|
||||||
|
|
||||||
|
@ -49,8 +49,8 @@ sysdep_headers += sys/mount.h sys/acct.h sys/sysctl.h \
|
|||||||
bits/mman-linux.h \
|
bits/mman-linux.h \
|
||||||
bits/siginfo-arch.h bits/siginfo-consts-arch.h
|
bits/siginfo-arch.h bits/siginfo-consts-arch.h
|
||||||
|
|
||||||
tests += tst-clone tst-clone2 tst-fanotify tst-personality tst-quota \
|
tests += tst-clone tst-clone2 tst-clone3 tst-fanotify tst-personality \
|
||||||
tst-sync_file_range test-errno-linux
|
tst-quota tst-sync_file_range test-errno-linux
|
||||||
|
|
||||||
# Generate the list of SYS_* macros for the system calls (__NR_* macros).
|
# Generate the list of SYS_* macros for the system calls (__NR_* macros).
|
||||||
|
|
||||||
|
@ -23,12 +23,6 @@
|
|||||||
#define _ERRNO_H 1
|
#define _ERRNO_H 1
|
||||||
#include <bits/errno.h>
|
#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
|
/* int clone(int (*fn)(void *arg), x0
|
||||||
void *child_stack, x1
|
void *child_stack, x1
|
||||||
int flags, x2
|
int flags, x2
|
||||||
@ -84,7 +78,8 @@ thread_start:
|
|||||||
blr x10
|
blr x10
|
||||||
|
|
||||||
/* We are done, pass the return value through x0. */
|
/* We are done, pass the return value through x0. */
|
||||||
b HIDDEN_JUMPTARGET(_exit)
|
mov x8, #SYS_ify(exit)
|
||||||
|
svc 0x0
|
||||||
cfi_endproc
|
cfi_endproc
|
||||||
.size thread_start, .-thread_start
|
.size thread_start, .-thread_start
|
||||||
|
|
||||||
|
@ -23,8 +23,6 @@
|
|||||||
#define _ERRNO_H 1
|
#define _ERRNO_H 1
|
||||||
#include <bits/errno.h>
|
#include <bits/errno.h>
|
||||||
|
|
||||||
#define CLONE_VM 0x00000100
|
|
||||||
|
|
||||||
/* int clone(int (*fn)(void *arg), void *child_stack, int flags,
|
/* int clone(int (*fn)(void *arg), void *child_stack, int flags,
|
||||||
void *arg, pid_t *ptid, void *tls, pid_t *ctid);
|
void *arg, pid_t *ptid, void *tls, pid_t *ctid);
|
||||||
|
|
||||||
@ -100,13 +98,8 @@ thread_start:
|
|||||||
jsr ra, (pv)
|
jsr ra, (pv)
|
||||||
ldgp gp, 0(ra)
|
ldgp gp, 0(ra)
|
||||||
|
|
||||||
/* Call _exit rather than doing it inline for breakpoint purposes. */
|
ldiq v0, __NR_exit
|
||||||
mov v0, a0
|
call_pal PAL_callsys
|
||||||
#ifdef PIC
|
|
||||||
bsr ra, HIDDEN_JUMPTARGET(_exit) !samegp
|
|
||||||
#else
|
|
||||||
jsr ra, HIDDEN_JUMPTARGET(_exit)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Die horribly. */
|
/* Die horribly. */
|
||||||
.align 4
|
.align 4
|
||||||
|
@ -24,9 +24,6 @@
|
|||||||
#define _ERRNO_H 1
|
#define _ERRNO_H 1
|
||||||
#include <bits/errno.h>
|
#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,
|
/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
|
||||||
pid_t *ptid, struct user_desc *tls, pid_t *ctid); */
|
pid_t *ptid, struct user_desc *tls, pid_t *ctid); */
|
||||||
|
|
||||||
@ -76,7 +73,8 @@ PSEUDO_END (__clone)
|
|||||||
BLX (ip)
|
BLX (ip)
|
||||||
|
|
||||||
@ and we are done, passing the return value through r0
|
@ and we are done, passing the return value through r0
|
||||||
b PLTJMP(HIDDEN_JUMPTARGET(_exit))
|
ldr r7, =SYS_ify(exit)
|
||||||
|
swi 0x0
|
||||||
|
|
||||||
.fnend
|
.fnend
|
||||||
|
|
||||||
|
@ -148,10 +148,10 @@ ENTRY(__clone)
|
|||||||
copy %r4, %r19
|
copy %r4, %r19
|
||||||
#endif
|
#endif
|
||||||
/* The call to _exit needs saved r19. */
|
/* The call to _exit needs saved r19. */
|
||||||
bl _exit, %rp
|
ble 0x100(%sr2, %r0)
|
||||||
copy %ret0, %arg0
|
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. */
|
We do not restore r4, or the stack state. */
|
||||||
iitlbp %r0, (%sr0, %r0)
|
iitlbp %r0, (%sr0, %r0)
|
||||||
|
|
||||||
|
@ -39,8 +39,6 @@
|
|||||||
#define __NR_clone 120
|
#define __NR_clone 120
|
||||||
#define SYS_clone 120
|
#define SYS_clone 120
|
||||||
|
|
||||||
#define CLONE_VM 0x00000100
|
|
||||||
|
|
||||||
.text
|
.text
|
||||||
ENTRY (__clone)
|
ENTRY (__clone)
|
||||||
/* Sanity check arguments. */
|
/* Sanity check arguments. */
|
||||||
|
@ -74,11 +74,11 @@ ENTRY(__clone2)
|
|||||||
mov b6=out1
|
mov b6=out1
|
||||||
br.call.dptk.many rp=b6 /* Call fn(arg) in the child */
|
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
|
mov gp=loc0
|
||||||
.globl HIDDEN_JUMPTARGET(_exit)
|
mov r15=SYS_ify (exit)
|
||||||
br.call.dpnt.many rp=HIDDEN_JUMPTARGET(_exit)
|
.save rp, r0
|
||||||
/* call _exit with result from fn. */
|
break __BREAK_SYSCALL
|
||||||
ret /* Not reached. */
|
ret /* Not reached. */
|
||||||
PSEUDO_END(__clone2)
|
PSEUDO_END(__clone2)
|
||||||
|
|
||||||
|
@ -24,8 +24,6 @@
|
|||||||
#include <bits/errno.h>
|
#include <bits/errno.h>
|
||||||
#include <tls.h>
|
#include <tls.h>
|
||||||
|
|
||||||
#define CLONE_VM 0x00000100
|
|
||||||
|
|
||||||
/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
|
/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
|
||||||
void *parent_tidptr, void *tls, void *child_tidptr) */
|
void *parent_tidptr, void *tls, void *child_tidptr) */
|
||||||
|
|
||||||
|
@ -25,9 +25,6 @@
|
|||||||
#include <bits/errno.h>
|
#include <bits/errno.h>
|
||||||
#include <tls.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,
|
/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
|
||||||
void *parent_tidptr, void *tls, void *child_tidptr) */
|
void *parent_tidptr, void *tls, void *child_tidptr) */
|
||||||
|
|
||||||
@ -137,14 +134,9 @@ L(thread_start):
|
|||||||
/* Call the user's function. */
|
/* Call the user's function. */
|
||||||
jal t9
|
jal t9
|
||||||
|
|
||||||
/* Call _exit rather than doing it inline for breakpoint purposes. */
|
|
||||||
move a0,v0
|
move a0,v0
|
||||||
#ifdef __PIC__
|
li v0,__NR_exit
|
||||||
PTR_LA t9,_exit
|
syscall
|
||||||
jalr t9
|
|
||||||
#else
|
|
||||||
jal _exit
|
|
||||||
#endif
|
|
||||||
|
|
||||||
END(__thread_start)
|
END(__thread_start)
|
||||||
|
|
||||||
|
@ -25,8 +25,6 @@
|
|||||||
#include <bits/errno.h>
|
#include <bits/errno.h>
|
||||||
#include <tcb-offsets.h>
|
#include <tcb-offsets.h>
|
||||||
|
|
||||||
#define CLONE_VM 0x00000100
|
|
||||||
|
|
||||||
/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
|
/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
|
||||||
void *parent_tidptr, void *tls, void *child_tidptr) */
|
void *parent_tidptr, void *tls, void *child_tidptr) */
|
||||||
|
|
||||||
@ -75,18 +73,9 @@ thread_start:
|
|||||||
/* Call the user's function. */
|
/* Call the user's function. */
|
||||||
callr r5
|
callr r5
|
||||||
|
|
||||||
/* _exit with the result. */
|
/* exit with the result. */
|
||||||
mov r4, r2
|
movi r2, SYS_ify (exit)
|
||||||
#ifdef PIC
|
trap
|
||||||
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
|
|
||||||
cfi_endproc
|
cfi_endproc
|
||||||
|
|
||||||
cfi_startproc
|
cfi_startproc
|
||||||
|
@ -20,10 +20,6 @@
|
|||||||
#define _ERRNO_H 1
|
#define _ERRNO_H 1
|
||||||
#include <bits/errno.h>
|
#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
|
/* This is the only really unusual system call in PPC linux, but not
|
||||||
because of any weirdness in the system call itself; because of
|
because of any weirdness in the system call itself; because of
|
||||||
all the freaky stuff we have to do to make the call useful. */
|
all the freaky stuff we have to do to make the call useful. */
|
||||||
@ -80,8 +76,7 @@ ENTRY (__clone)
|
|||||||
mtctr r30
|
mtctr r30
|
||||||
mr r3,r31
|
mr r3,r31
|
||||||
bctrl
|
bctrl
|
||||||
/* Call _exit with result from procedure. */
|
DO_CALL(SYS_ify(exit))
|
||||||
b HIDDEN_JUMPTARGET(_exit)
|
|
||||||
|
|
||||||
L(parent):
|
L(parent):
|
||||||
/* Parent. Restore registers & return. */
|
/* Parent. Restore registers & return. */
|
||||||
|
@ -20,9 +20,6 @@
|
|||||||
#define _ERRNO_H 1
|
#define _ERRNO_H 1
|
||||||
#include <bits/errno.h>
|
#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
|
/* This is the only really unusual system call in PPC linux, but not
|
||||||
because of any weirdness in the system call itself; because of
|
because of any weirdness in the system call itself; because of
|
||||||
all the freaky stuff we have to do to make the call useful. */
|
all the freaky stuff we have to do to make the call useful. */
|
||||||
@ -84,15 +81,11 @@ ENTRY (__clone)
|
|||||||
mr r3,r31
|
mr r3,r31
|
||||||
bctrl
|
bctrl
|
||||||
ld r2,FRAME_TOC_SAVE(r1)
|
ld r2,FRAME_TOC_SAVE(r1)
|
||||||
/* Call _exit with result from procedure. */
|
|
||||||
#ifdef SHARED
|
DO_CALL(SYS_ify(exit))
|
||||||
b JUMPTARGET(__GI__exit)
|
|
||||||
#else
|
|
||||||
bl JUMPTARGET(_exit)
|
|
||||||
/* We won't ever get here but provide a nop so that the linker
|
/* We won't ever get here but provide a nop so that the linker
|
||||||
will insert a toc adjusting stub if necessary. */
|
will insert a toc adjusting stub if necessary. */
|
||||||
nop
|
nop
|
||||||
#endif
|
|
||||||
|
|
||||||
L(badargs):
|
L(badargs):
|
||||||
cfi_startproc
|
cfi_startproc
|
||||||
|
@ -73,25 +73,8 @@ ENTRY(__clone)
|
|||||||
mov.l @(4,r15), r4
|
mov.l @(4,r15), r4
|
||||||
|
|
||||||
/* we are done, passing the return value through r0 */
|
/* we are done, passing the return value through r0 */
|
||||||
mov.l .L3, r1
|
mov #+SYS_ify(exit), r3
|
||||||
#ifdef SHARED
|
trapa #0x15
|
||||||
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
|
|
||||||
.align 2
|
.align 2
|
||||||
.LG:
|
.LG:
|
||||||
.long _GLOBAL_OFFSET_TABLE_
|
.long _GLOBAL_OFFSET_TABLE_
|
||||||
|
@ -24,8 +24,6 @@
|
|||||||
#include <tcb-offsets.h>
|
#include <tcb-offsets.h>
|
||||||
#include <sysdep.h>
|
#include <sysdep.h>
|
||||||
|
|
||||||
#define CLONE_VM 0x00000100
|
|
||||||
|
|
||||||
/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
|
/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
|
||||||
pid_t *ptid, void *tls, pid_t *ctid); */
|
pid_t *ptid, void *tls, pid_t *ctid); */
|
||||||
|
|
||||||
@ -81,7 +79,8 @@ __thread_start:
|
|||||||
mov %g0, %fp /* terminate backtrace */
|
mov %g0, %fp /* terminate backtrace */
|
||||||
call %g2
|
call %g2
|
||||||
mov %g3,%o0
|
mov %g3,%o0
|
||||||
call HIDDEN_JUMPTARGET(_exit),0
|
set __NR_exit, %g1
|
||||||
|
ta 0x10
|
||||||
nop
|
nop
|
||||||
|
|
||||||
.size __thread_start, .-__thread_start
|
.size __thread_start, .-__thread_start
|
||||||
|
@ -24,8 +24,6 @@
|
|||||||
#include <tcb-offsets.h>
|
#include <tcb-offsets.h>
|
||||||
#include <sysdep.h>
|
#include <sysdep.h>
|
||||||
|
|
||||||
#define CLONE_VM 0x00000100
|
|
||||||
|
|
||||||
/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
|
/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
|
||||||
pid_t *ptid, void *tls, pid_t *ctid); */
|
pid_t *ptid, void *tls, pid_t *ctid); */
|
||||||
|
|
||||||
@ -78,7 +76,8 @@ __thread_start:
|
|||||||
mov %g0, %fp /* terminate backtrace */
|
mov %g0, %fp /* terminate backtrace */
|
||||||
call %g2
|
call %g2
|
||||||
mov %g3,%o0
|
mov %g3,%o0
|
||||||
call HIDDEN_JUMPTARGET(_exit),0
|
set __NR_exit, %g1
|
||||||
|
ta 0x6d
|
||||||
nop
|
nop
|
||||||
|
|
||||||
.size __thread_start, .-__thread_start
|
.size __thread_start, .-__thread_start
|
||||||
|
@ -168,10 +168,8 @@ ENTRY (__clone)
|
|||||||
move r0, r31
|
move r0, r31
|
||||||
jalr r32
|
jalr r32
|
||||||
}
|
}
|
||||||
{
|
moveli TREG_SYSCALL_NR_NAME, __NR_exit
|
||||||
j HIDDEN_JUMPTARGET(_exit)
|
swint1
|
||||||
info INFO_OP_CANNOT_BACKTRACE /* Notify backtracer to stop. */
|
|
||||||
}
|
|
||||||
PSEUDO_END (__clone)
|
PSEUDO_END (__clone)
|
||||||
|
|
||||||
libc_hidden_def (__clone)
|
libc_hidden_def (__clone)
|
||||||
|
96
sysdeps/unix/sysv/linux/tst-clone3.c
Normal file
96
sysdeps/unix/sysv/linux/tst-clone3.c
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
/* 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. */
|
||||||
|
|
||||||
|
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");
|
||||||
|
|
||||||
|
ctid = tid;
|
||||||
|
wait_tid (ctid);
|
||||||
|
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define EXPECTED_STATUS 2
|
||||||
|
#include <support/test-driver.c>
|
@ -23,8 +23,6 @@
|
|||||||
#include <bits/errno.h>
|
#include <bits/errno.h>
|
||||||
#include <asm-syntax.h>
|
#include <asm-syntax.h>
|
||||||
|
|
||||||
#define CLONE_VM 0x00000100
|
|
||||||
|
|
||||||
/* The userland implementation is:
|
/* The userland implementation is:
|
||||||
int clone (int (*fn)(void *arg), void *child_stack, int flags, void *arg),
|
int clone (int (*fn)(void *arg), void *child_stack, int flags, void *arg),
|
||||||
the kernel entry is:
|
the kernel entry is:
|
||||||
@ -97,7 +95,8 @@ L(thread_start):
|
|||||||
call *%rax
|
call *%rax
|
||||||
/* Call exit with return value from function call. */
|
/* Call exit with return value from function call. */
|
||||||
movq %rax, %rdi
|
movq %rax, %rdi
|
||||||
call HIDDEN_JUMPTARGET (_exit)
|
movl $SYS_ify(exit), %eax
|
||||||
|
syscall
|
||||||
cfi_endproc;
|
cfi_endproc;
|
||||||
|
|
||||||
cfi_startproc;
|
cfi_startproc;
|
||||||
|
Loading…
Reference in New Issue
Block a user