diff options
-rw-r--r-- | nptl/Banner | 2 | ||||
-rw-r--r-- | nptl/ChangeLog | 4 | ||||
-rw-r--r-- | nptl/Makefile | 16 | ||||
-rw-r--r-- | nptl/tst-cancel4.c | 140 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/wait.c | 8 |
5 files changed, 139 insertions, 31 deletions
diff --git a/nptl/Banner b/nptl/Banner index 2c6bea0297..03776acd77 100644 --- a/nptl/Banner +++ b/nptl/Banner @@ -1 +1 @@ -NPTL 0.46 by Ulrich Drepper +NPTL 0.47 by Ulrich Drepper diff --git a/nptl/ChangeLog b/nptl/ChangeLog index 66371c0fd3..ed81d6e7ff 100644 --- a/nptl/ChangeLog +++ b/nptl/ChangeLog @@ -1,5 +1,9 @@ 2003-06-16 Ulrich Drepper <drepper@redhat.com> + * Makefile: Add CFLAGS definition to compile function wrappers + duplicated from libc with exceptions. + * tst-cancel4.c: Also check cancellation handlers. + * Makefile: Add rules to build and run tst-cancel16 and tst-cancelx16. Add missing CFLAGS definitions. * tst-cancel16.c: New file. diff --git a/nptl/Makefile b/nptl/Makefile index 28c745aed0..38e11c01d7 100644 --- a/nptl/Makefile +++ b/nptl/Makefile @@ -161,6 +161,22 @@ CFLAGS-pthread_cond_timedwait.c = -fexceptions -fasynchronous-unwind-tables CFLAGS-sem_wait.c = -fexceptions -fasynchronous-unwind-tables CFLAGS-sem_timedwait.c = -fexceptions -fasynchronous-unwind-tables +# These are the function wrappers we have to duplicate here. +CFLAGS-fcntl.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-lockf.c = -fexceptions +CFLAGS-pread.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-pread64.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-pwrite.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-pwrite64.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-wait.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-waitpid.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-sigwait.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-msgrcv.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-msgsnd.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-tcdrain.c = -fexceptions -fasynchronous-unwind-tables + +CFLAGS-pt-system.c = -fexceptions + # Don't generate deps for calls with no sources. See sysdeps/unix/Makefile. omit-deps = $(unix-syscalls:%=ptw-%) diff --git a/nptl/tst-cancel4.c b/nptl/tst-cancel4.c index 6fb447715c..4a15bbd3b2 100644 --- a/nptl/tst-cancel4.c +++ b/nptl/tst-cancel4.c @@ -64,6 +64,16 @@ static int fds[2]; static pthread_barrier_t b2; +/* Cleanup handling test. */ +static int cl_called; + +static void +cl (void *arg) +{ + ++cl_called; +} + + static void * tf_read (void *arg) { @@ -74,11 +84,15 @@ tf_read (void *arg) exit (1); } + pthread_cleanup_push (cl, NULL); + char buf[100]; ssize_t s = read (fds[0], buf, sizeof (buf)); printf ("%s: read returns with %zd\n", __FUNCTION__, s); + pthread_cleanup_pop (0); + exit (1); } @@ -93,12 +107,16 @@ tf_readv (void *arg) exit (1); } + pthread_cleanup_push (cl, NULL); + char buf[100]; struct iovec iov[1] = { [0] = { .iov_base = buf, .iov_len = sizeof (buf) } }; ssize_t s = readv (fds[0], iov, 1); printf ("%s: readv returns with %zd\n", __FUNCTION__, s); + pthread_cleanup_pop (0); + exit (1); } @@ -113,12 +131,16 @@ tf_write (void *arg) exit (1); } + pthread_cleanup_push (cl, NULL); + char buf[100000]; memset (buf, '\0', sizeof (buf)); ssize_t s = write (fds[1], buf, sizeof (buf)); printf ("%s: write returns with %zd\n", __FUNCTION__, s); + pthread_cleanup_pop (0); + exit (1); } @@ -133,6 +155,8 @@ tf_writev (void *arg) exit (1); } + pthread_cleanup_push (cl, NULL); + char buf[100000]; memset (buf, '\0', sizeof (buf)); struct iovec iov[1] = { [0] = { .iov_base = buf, .iov_len = sizeof (buf) } }; @@ -140,6 +164,8 @@ tf_writev (void *arg) printf ("%s: writev returns with %zd\n", __FUNCTION__, s); + pthread_cleanup_pop (0); + exit (1); } @@ -154,8 +180,12 @@ tf_sleep (void *arg) exit (1); } + pthread_cleanup_push (cl, NULL); + sleep (1000000); + pthread_cleanup_pop (0); + printf ("%s: sleep returns\n", __FUNCTION__); exit (1); @@ -172,8 +202,12 @@ tf_usleep (void *arg) exit (1); } + pthread_cleanup_push (cl, NULL); + usleep ((useconds_t) ULONG_MAX); + pthread_cleanup_pop (0); + printf ("%s: usleep returns\n", __FUNCTION__); exit (1); @@ -190,10 +224,14 @@ tf_nanosleep (void *arg) exit (1); } + pthread_cleanup_push (cl, NULL); + struct timespec ts = { .tv_sec = 10000000, .tv_nsec = 0 }; while (nanosleep (&ts, &ts) != 0) continue; + pthread_cleanup_pop (0); + printf ("%s: nanosleep returns\n", __FUNCTION__); exit (1); @@ -214,11 +252,15 @@ tf_select (void *arg) FD_ZERO (&rfs); FD_SET (fds[0], &rfs); + pthread_cleanup_push (cl, NULL); + int s = select (fds[0] + 1, &rfs, NULL, NULL, NULL); printf ("%s: select returns with %d (%s)\n", __FUNCTION__, s, strerror (errno)); + pthread_cleanup_pop (0); + exit (1); } @@ -237,11 +279,15 @@ tf_pselect (void *arg) FD_ZERO (&rfs); FD_SET (fds[0], &rfs); + pthread_cleanup_push (cl, NULL); + int s = pselect (fds[0] + 1, &rfs, NULL, NULL, NULL, NULL); printf ("%s: pselect returns with %d (%s)\n", __FUNCTION__, s, strerror (errno)); + pthread_cleanup_pop (0); + exit (1); } @@ -258,11 +304,15 @@ tf_poll (void *arg) struct pollfd rfs[1] = { [0] = { .fd = fds[0], .events = POLLIN } }; + pthread_cleanup_push (cl, NULL); + int s = poll (rfs, 1, -1); printf ("%s: poll returns with %d (%s)\n", __FUNCTION__, s, strerror (errno)); + pthread_cleanup_pop (0); + exit (1); } @@ -291,11 +341,15 @@ tf_wait (void *arg) exit (0); } + pthread_cleanup_push (cl, NULL); + int s = wait (NULL); printf ("%s: wait returns with %d (%s)\n", __FUNCTION__, s, strerror (errno)); + pthread_cleanup_pop (0); + exit (1); } @@ -324,11 +378,15 @@ tf_waitpid (void *arg) exit (0); } + pthread_cleanup_push (cl, NULL); + int s = waitpid (-1, NULL, 0); printf ("%s: waitpid returns with %d (%s)\n", __FUNCTION__, s, strerror (errno)); + pthread_cleanup_pop (0); + exit (1); } @@ -357,35 +415,41 @@ tf_waitid (void *arg) exit (0); } + pthread_cleanup_push (cl, NULL); + siginfo_t si; int s = waitid (P_PID, pid, &si, 0); printf ("%s: waitid returns with %d (%s)\n", __FUNCTION__, s, strerror (errno)); + pthread_cleanup_pop (0); + exit (1); } static struct { + const char *name; void *(*tf) (void *); int nb; } tests[] = { - { tf_read, 2 }, - { tf_readv, 2 }, - { tf_select, 2 }, - { tf_pselect, 2 }, - { tf_poll, 2 }, - { tf_write, 2 }, - { tf_writev, 2}, - { tf_sleep, 2 }, - { tf_usleep, 2 }, - { tf_nanosleep, 2 }, - { tf_wait, 2 }, - { tf_waitid, 2 }, - { tf_waitpid, 2 }, +#define ADD_TEST(name, nbar) { #name, tf_##name, nbar } + ADD_TEST (read, 2), + ADD_TEST (readv, 2), + ADD_TEST (select, 2), + ADD_TEST (pselect, 2), + ADD_TEST (poll, 2), + ADD_TEST (write, 2), + ADD_TEST (writev, 2), + ADD_TEST (sleep, 2), + ADD_TEST (usleep, 2), + ADD_TEST (nanosleep, 2), + ADD_TEST (wait, 2), + ADD_TEST (waitid, 2), + ADD_TEST (waitpid, 2), }; #define ntest_tf (sizeof (tests) / sizeof (tests[0])) @@ -399,6 +463,7 @@ do_test (void) exit (1); } + int result = 0; size_t cnt; for (cnt = 0; cnt < ntest_tf; ++cnt) { @@ -408,19 +473,23 @@ do_test (void) exit (1); } - /* read(2) test. */ + /* Reset the counter for the cleanup handler. */ + cl_called = 0; + pthread_t th; if (pthread_create (&th, NULL, tests[cnt].tf, NULL) != 0) { - printf ("create for round %zd test failed\n", cnt); - exit (1); + printf ("create for '%s' test failed\n", tests[cnt].name); + result = 1; + continue; } int r = pthread_barrier_wait (&b2); if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD) { printf ("%s: barrier_wait failed\n", __FUNCTION__); - exit (1); + result = 1; + continue; } struct timespec ts = { .tv_sec = 0, .tv_nsec = 100000000 }; @@ -429,31 +498,50 @@ do_test (void) if (pthread_cancel (th) != 0) { - printf ("cancel in round %zd failed\n", cnt); - exit (1); + printf ("cancel for '%s' failed\n", tests[cnt].name); + result = 1; + continue; } void *status; if (pthread_join (th, &status) != 0) { - printf ("join in round %zd failed\n", cnt); - exit (1); + printf ("join for '%s' failed\n", tests[cnt].name); + result = 1; + continue; } if (status != PTHREAD_CANCELED) { - printf ("thread in round %zd not canceled\n", cnt); - exit (1); + printf ("thread for '%s' not canceled\n", tests[cnt].name); + result = 1; + continue; } - printf ("test %zd successful\n", cnt); if (pthread_barrier_destroy (&b2) != 0) { puts ("barrier_destroy failed"); - exit (1); + result = 1; + continue; } + + if (cl_called == 0) + { + printf ("cleanup handler not called for '%s'\n", tests[cnt].name); + result = 1; + continue; + } + if (cl_called > 1) + { + printf ("cleanup handler called more than once for '%s'\n", + tests[cnt].name); + result = 1; + continue; + } + + printf ("test of '%s' successful\n", tests[cnt].name); } - return 0; + return result; } #define TIMEOUT 60 diff --git a/sysdeps/unix/sysv/linux/wait.c b/sysdeps/unix/sysv/linux/wait.c index 3e39ad4bf1..39d1066ddd 100644 --- a/sysdeps/unix/sysv/linux/wait.c +++ b/sysdeps/unix/sysv/linux/wait.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 1995, 1996, 1997, 2002 Free Software Foundation, Inc. +/* Copyright (C) 1991,1995,1996,1997,2002,2003 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 @@ -24,7 +24,7 @@ /* Wait for a child to die. When one does, put its status in *STAT_LOC and return its process ID. For errors, return (pid_t) -1. */ -__pid_t +pid_t __libc_wait (__WAIT_STATUS_DEFN stat_loc) { if (SINGLE_THREAD_P) @@ -33,8 +33,8 @@ __libc_wait (__WAIT_STATUS_DEFN stat_loc) int oldtype = LIBC_CANCEL_ASYNC (); - int result = INLINE_SYSCALL (wait4, 4, WAIT_ANY, stat_loc, 0, - (struct rusage *) NULL); + pid_t result = INLINE_SYSCALL (wait4, 4, WAIT_ANY, stat_loc, 0, + (struct rusage *) NULL); LIBC_CANCEL_RESET (oldtype); |