2004-02-09  Jakub Jelinek  <jakub@redhat.com>

	* posix/Makefile (tests): Add tst-vfork2.
	* posix/tst-vfork1.c (do_test): Fix comment.
	* posix/tst-vfork2.c: New test.
This commit is contained in:
Ulrich Drepper 2004-03-10 05:25:48 +00:00
parent 9363dbb847
commit 8b9d605485
15 changed files with 304 additions and 13 deletions

View File

@ -1,3 +1,9 @@
2004-02-09 Jakub Jelinek <jakub@redhat.com>
* posix/Makefile (tests): Add tst-vfork2.
* posix/tst-vfork1.c (do_test): Fix comment.
* posix/tst-vfork2.c: New test.
2004-03-09 Ulrich Drepper <drepper@redhat.com> 2004-03-09 Ulrich Drepper <drepper@redhat.com>
* elf/dl-lookup.c (_dl_lookup_symbol_x): Fix possible NULL pointer * elf/dl-lookup.c (_dl_lookup_symbol_x): Fix possible NULL pointer

View File

@ -1,3 +1,24 @@
2004-02-09 Jakub Jelinek <jakub@redhat.com>
* sysdeps/unix/sysv/linux/i386/vfork.S (SAVE_PID): Negate PID
if non-zero and set to INT_MIN if zero.
* sysdeps/unix/sysv/linux/x86_64/vfork.S (SAVE_PID): Likewise.
* sysdeps/unix/sysv/linux/i386/pt-vfork.S: Include tcb-offsets.h.
(SAVE_PID, RESTORE_PID): Define.
(__vfork): Use it.
* sysdeps/unix/sysv/linux/x86_64/pt-vfork.S: Include tcb-offsets.h.
Use relative path to avoid including NPTL i386/vfork.S.
(SAVE_PID, RESTORE_PID): Define.
* sysdeps/unix/sysv/linux/raise.c: Include limits.h.
(raise): Handle THREAD_SELF->pid INT_MIN the same as 0.
* Makefile (tests): Add tst-vfork1, tst-vfork2, tst-vfork1x and
tst-vfork2x.
(tests-reverse): Add tst-vfork1x and tst-vfork2x.
* tst-vfork1.c: New test.
* tst-vfork2.c: New test.
* tst-vfork1x.c: New test.
* tst-vfork2x.c: New test.
2004-03-08 Ulrich Drepper <drepper@redhat.com> 2004-03-08 Ulrich Drepper <drepper@redhat.com>
* sysdeps/i386/tcb-offsets.sym: Add PID. * sysdeps/i386/tcb-offsets.sym: Add PID.

View File

@ -237,7 +237,8 @@ tests = tst-attr1 tst-attr2 tst-attr3 \
tst-context1 \ tst-context1 \
tst-sched1 \ tst-sched1 \
tst-backtrace1 \ tst-backtrace1 \
tst-oddstacklimit tst-oddstacklimit \
tst-vfork1 tst-vfork2 tst-vfork1x tst-vfork2x
# Files which must not be linked with libpthread. # Files which must not be linked with libpthread.
tests-nolibpthread = tst-unload tests-nolibpthread = tst-unload
@ -337,7 +338,7 @@ ifeq ($(build-static),yes)
tests-static += tst-locale1 tst-locale2 tests-static += tst-locale1 tst-locale2
endif endif
# These tests are linked with libc before libpthread # These tests are linked with libc before libpthread
tests-reverse += tst-cancel5 tst-cancel23 tests-reverse += tst-cancel5 tst-cancel23 tst-vfork1x tst-vfork2x
include ../Rules include ../Rules

View File

@ -1,4 +1,4 @@
/* Copyright (C) 1999, 2002 Free Software Foundation, Inc. /* Copyright (C) 1999, 2002, 2004 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
Contributed by Andreas Schwab <schwab@gnu.org>. Contributed by Andreas Schwab <schwab@gnu.org>.
@ -21,6 +21,21 @@
#define _ERRNO_H 1 #define _ERRNO_H 1
#include <bits/errno.h> #include <bits/errno.h>
#include <kernel-features.h> #include <kernel-features.h>
#include <tcb-offsets.h>
/* Save the PID value. */
#define SAVE_PID \
movl %gs:PID, %edx; \
movl %edx, %eax; \
negl %eax; \
movl %eax, %gs:PID
/* Restore the old PID value in the parent. */
#define RESTORE_PID \
testl %eax, %eax; \
je 1f; \
movl %edx, %gs:PID; \
1:
/* Clone the calling process, but without copying the whole address space. /* Clone the calling process, but without copying the whole address space.
The calling process is suspended until the new process exits or is The calling process is suspended until the new process exits or is
@ -31,10 +46,14 @@ ENTRY (__vfork)
/* Pop the return PC value into ECX. */ /* Pop the return PC value into ECX. */
popl %ecx popl %ecx
SAVE_PID
/* Stuff the syscall number in EAX and enter into the kernel. */ /* Stuff the syscall number in EAX and enter into the kernel. */
movl $SYS_ify (vfork), %eax movl $SYS_ify (vfork), %eax
int $0x80 int $0x80
RESTORE_PID
/* Jump to the return PC. Don't jump directly since this /* Jump to the return PC. Don't jump directly since this
disturbs the branch target cache. Instead push the return disturbs the branch target cache. Instead push the return
address back on the stack. */ address back on the stack. */

View File

@ -21,9 +21,13 @@
/* Save the PID value. */ /* Save the PID value. */
#define SAVE_PID \ #define SAVE_PID \
movl %gs:PID, %edx; \ movl %gs:PID, %edx; \
movl $-1, %gs:PID movl %edx, %eax; \
negl %eax; \
jne 1f; \
movl $0x80000000, %eax; \
1: movl %eax, %gs:PID
/* Restore the old PID value in the parent. In the child store 0. */ /* Restore the old PID value in the parent. */
#define RESTORE_PID \ #define RESTORE_PID \
testl %eax, %eax; \ testl %eax, %eax; \
je 1f; \ je 1f; \

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. /* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
@ -18,6 +18,7 @@
02111-1307 USA. */ 02111-1307 USA. */
#include <errno.h> #include <errno.h>
#include <limits.h>
#include <signal.h> #include <signal.h>
#include <sysdep.h> #include <sysdep.h>
#include <nptl/pthreadP.h> #include <nptl/pthreadP.h>
@ -53,10 +54,10 @@ raise (sig)
#if __ASSUME_TGKILL || defined __NR_tgkill #if __ASSUME_TGKILL || defined __NR_tgkill
else else
/* raise is an async-safe function. It could be called while the /* raise is an async-safe function. It could be called while the
fork function temporarily invalidated the PID field. Adjust for fork/vfork function temporarily invalidated the PID field. Adjust for
that. */ that. */
if (__builtin_expect (pid <= 0, 0)) if (__builtin_expect (pid <= 0, 0))
pid = pid == 0 ? selftid : -pid; pid = (pid & INT_MAX) == 0 ? selftid : -pid;
#endif #endif
#if __ASSUME_TGKILL #if __ASSUME_TGKILL

View File

@ -1 +1,33 @@
#include <sysdeps/unix/sysv/linux/x86_64/vfork.S> /* Copyright (C) 2004 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, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <tcb-offsets.h>
#define SAVE_PID \
movl %fs:PID, %esi; \
movl %esi, %edx; \
negl %edx; \
movl %edx, %fs:PID
#define RESTORE_PID \
testq %rax, %rax; \
je 1f; \
movl %esi, %fs:PID; \
1:
#include <../../../../../../sysdeps/unix/sysv/linux/x86_64/vfork.S>

View File

@ -20,7 +20,11 @@
#define SAVE_PID \ #define SAVE_PID \
movl %fs:PID, %esi; \ movl %fs:PID, %esi; \
movl $-1, %fs:PID movl $0x80000000, %ecx; \
movl %esi, %edx; \
negl %edx; \
cmove %ecx, %edx; \
movl %edx, %fs:PID
#define RESTORE_PID \ #define RESTORE_PID \
testq %rax, %rax; \ testq %rax, %rax; \

1
nptl/tst-vfork1.c Normal file
View File

@ -0,0 +1 @@
#include <posix/tst-vfork1.c>

1
nptl/tst-vfork1x.c Normal file
View File

@ -0,0 +1 @@
#include <posix/tst-vfork1.c>

1
nptl/tst-vfork2.c Normal file
View File

@ -0,0 +1 @@
#include <posix/tst-vfork2.c>

1
nptl/tst-vfork2x.c Normal file
View File

@ -0,0 +1 @@
#include <posix/tst-vfork2.c>

View File

@ -81,7 +81,7 @@ tests := tstgetopt testfnm runtests runptests \
bug-regex17 bug-regex18 bug-regex19 bug-regex20 \ bug-regex17 bug-regex18 bug-regex19 bug-regex20 \
bug-regex21 bug-regex22 bug-regex23 tst-nice tst-nanosleep \ bug-regex21 bug-regex22 bug-regex23 tst-nice tst-nanosleep \
transbug tst-rxspencer tst-pcre tst-boost \ transbug tst-rxspencer tst-pcre tst-boost \
bug-ga1 tst-vfork1 bug-ga1 tst-vfork1 tst-vfork2
xtests := bug-ga2 xtests := bug-ga2
ifeq (yes,$(build-shared)) ifeq (yes,$(build-shared))
test-srcs := globtest test-srcs := globtest

View File

@ -1,4 +1,4 @@
/* Test for chmod functions. /* Test for vfork functions.
Copyright (C) 2004 Free Software Foundation, Inc. Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2004. Contributed by Ulrich Drepper <drepper@redhat.com>, 2004.
@ -26,7 +26,7 @@
#include <sys/wait.h> #include <sys/wait.h>
/* This test relies on non-POSIX functionality since the child /* This test relies on non-POSIX functionality since the child
processes call write. */ processes call write and getpid. */
static int static int
do_test (void) do_test (void)
{ {

199
posix/tst-vfork2.c Normal file
View File

@ -0,0 +1,199 @@
/* Test for vfork functions.
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2004.
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, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>
int raise_fail;
static void
alrm (int sig)
{
if (raise (SIGUSR1) < 0)
raise_fail = 1;
}
/* This test relies on non-POSIX functionality since the child
processes call write, nanosleep and getpid. */
static int
do_test (void)
{
int result = 0;
int fd[2];
signal (SIGUSR1, SIG_IGN);
struct sigaction sa;
sa.sa_handler = alrm;
sigemptyset (&sa.sa_mask);
sa.sa_flags = 0;
if (sigaction (SIGALRM, &sa, NULL) < 0)
{
puts ("couldn't set up SIGALRM handler");
return 1;
}
if (pipe (fd) == -1)
{
puts ("pipe failed");
return 1;
}
struct itimerval it;
it.it_value.tv_sec = 0;
it.it_value.tv_usec = 200 * 1000;
it.it_interval = it.it_value;
if (setitimer (ITIMER_REAL, &it, NULL) < 0)
{
puts ("couldn't set up timer");
return 1;
}
/* First vfork() without previous getpid(). */
pid_t p1;
if ((p1 = vfork ()) == 0)
{
pid_t p = getpid ();
struct timespec ts;
ts.tv_sec = 1;
ts.tv_nsec = 0;
TEMP_FAILURE_RETRY (nanosleep (&ts, &ts));
_exit (TEMP_FAILURE_RETRY (write (fd[1], &p, sizeof (p))) != sizeof (p));
}
else if (p1 == -1)
{
puts ("1st vfork failed");
result = 1;
}
memset (&it, 0, sizeof (it));
setitimer (ITIMER_REAL, &it, NULL);
pid_t p2 = 0;
if (TEMP_FAILURE_RETRY (read (fd[0], &p2, sizeof (pid_t))) != sizeof (pid_t))
{
puts ("1st read failed");
result = 1;
}
int r;
if (TEMP_FAILURE_RETRY (waitpid (p1, &r, 0)) != p1)
{
puts ("1st waitpid failed");
result = 1;
}
else if (r != 0)
{
puts ("write in 1st child failed");
result = 1;
}
/* Main process' ID. */
pid_t p0 = getpid ();
/* vfork() again, but after a getpid() in the main process. */
pid_t p3;
if ((p3 = vfork ()) == 0)
{
pid_t p = getpid ();
_exit (TEMP_FAILURE_RETRY (write (fd[1], &p, sizeof (p))) != sizeof (p));
}
else if (p1 == -1)
{
puts ("2nd vfork failed");
result = 1;
}
pid_t p4;
if (TEMP_FAILURE_RETRY (read (fd[0], &p4, sizeof (pid_t))) != sizeof (pid_t))
{
puts ("2nd read failed");
result = 1;
}
if (TEMP_FAILURE_RETRY (waitpid (p3, &r, 0)) != p3)
{
puts ("2nd waitpid failed");
result = 1;
}
else if (r != 0)
{
puts ("write in 2nd child failed");
result = 1;
}
/* And getpid in the main process again. */
pid_t p5 = getpid ();
/* Analysis of the results. */
if (p0 != p5)
{
printf ("p0(%ld) != p5(%ld)\n", (long int) p0, (long int) p5);
result = 1;
}
if (p0 == p1)
{
printf ("p0(%ld) == p1(%ld)\n", (long int) p0, (long int) p1);
result = 1;
}
if (p1 != p2)
{
printf ("p1(%ld) != p2(%ld)\n", (long int) p1, (long int) p2);
result = 1;
}
if (p0 == p3)
{
printf ("p0(%ld) == p3(%ld)\n", (long int) p0, (long int) p3);
result = 1;
}
if (p3 != p4)
{
printf ("p3(%ld) != p4(%ld)\n", (long int) p3, (long int) p4);
result = 1;
}
close (fd[0]);
close (fd[1]);
if (raise_fail)
{
puts ("raise failed");
result = 1;
}
if (result == 0)
puts ("All OK");
return result;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"