diff options
-rw-r--r-- | nptl/Banner | 2 | ||||
-rw-r--r-- | nptl/ChangeLog | 8 | ||||
-rw-r--r-- | nptl/Makefile | 1 | ||||
-rw-r--r-- | nptl/libc-cancellation.c | 3 | ||||
-rw-r--r-- | nptl/pthreadP.h | 4 | ||||
-rw-r--r-- | nptl/tst-cancel11.c | 123 |
6 files changed, 137 insertions, 4 deletions
diff --git a/nptl/Banner b/nptl/Banner index f11a2e32eb..288d93dbf8 100644 --- a/nptl/Banner +++ b/nptl/Banner @@ -1 +1 @@ -NPTL 0.33 by Ulrich Drepper +NPTL 0.34 by Ulrich Drepper diff --git a/nptl/ChangeLog b/nptl/ChangeLog index ca35ca14e0..d8467e8cda 100644 --- a/nptl/ChangeLog +++ b/nptl/ChangeLog @@ -1,3 +1,11 @@ +2003-04-03 Ulrich Drepper <drepper@redhat.com> + + * init.c (sigcancel_handler): Don't set EXITING_BIT here. + * libc-cancellation.c (__libc_enable_asynccancel): Likewise. + * pthreadP.h (__do_cancel): Set EXITING_BIT here. + * Makefile (tests): Add tst-cancel11. + * tst-cancel11.c: New file. + 2003-04-01 Ulrich Drepper <drepper@redhat.com> * pthread_create.c (deallocate_tsd): Clear/free memory after the last diff --git a/nptl/Makefile b/nptl/Makefile index 672e88a5ae..a7d592049e 100644 --- a/nptl/Makefile +++ b/nptl/Makefile @@ -151,6 +151,7 @@ tests = tst-attr1 tst-attr2 \ tst-atfork1 \ tst-cancel1 tst-cancel2 tst-cancel3 tst-cancel4 tst-cancel5 \ tst-cancel6 tst-cancel7 tst-cancel8 tst-cancel9 tst-cancel10 \ + tst-cancel11 \ tst-cleanup1 tst-cleanup2 tst-cleanup3 \ tst-flock1 tst-flock2 \ tst-signal1 tst-signal2 tst-signal3 tst-signal4 tst-signal5 \ diff --git a/nptl/libc-cancellation.c b/nptl/libc-cancellation.c index 0d584fbb33..344a2181c8 100644 --- a/nptl/libc-cancellation.c +++ b/nptl/libc-cancellation.c @@ -54,9 +54,6 @@ __libc_enable_asynccancel (void) THREAD_SETMEM (self, result, PTHREAD_CANCELED); - /* The thread is exiting now. */ - atomic_bit_set (&self->cancelhandling, EXITING_BIT); - __do_cancel (); /* NOTREACHED */ diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h index d90ac36091..725c87d6bb 100644 --- a/nptl/pthreadP.h +++ b/nptl/pthreadP.h @@ -29,6 +29,7 @@ #include <stackinfo.h> #include <internaltypes.h> #include <pthread-functions.h> +#include <atomic.h> /* Internal variables. */ @@ -149,6 +150,9 @@ __do_cancel (void) { struct pthread *self = THREAD_SELF; + /* Make sure we get no more cancellations. */ + atomic_bit_set (&self->cancelhandling, EXITING_BIT); + /* Throw an exception. */ // XXX TBI diff --git a/nptl/tst-cancel11.c b/nptl/tst-cancel11.c new file mode 100644 index 0000000000..235aef5c4d --- /dev/null +++ b/nptl/tst-cancel11.c @@ -0,0 +1,123 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2003. + + 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 <pthread.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + + +static pthread_barrier_t bar; +static int fd[2]; + + +static void +cleanup (void *arg) +{ + static int ncall; + + if (++ncall != 1) + { + puts ("second call to cleanup"); + exit (1); + } + + printf ("cleanup call #%d\n", ncall); +} + + +static void * +tf (void *arg) +{ + pthread_cleanup_push (cleanup, NULL); + + int e = pthread_barrier_wait (&bar); + if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) + { + puts ("tf: 1st barrier_wait failed"); + exit (1); + } + + /* This call should block and be cancelable. */ + char buf[20]; + read (fd[0], buf, sizeof (buf)); + + pthread_cleanup_pop (0); + + return NULL; +} + + +static int +do_test (void) +{ + pthread_t th; + + if (pthread_barrier_init (&bar, NULL, 2) != 0) + { + puts ("barrier_init failed"); + exit (1); + } + + if (pipe (fd) != 0) + { + puts ("pipe failed"); + exit (1); + } + + if (pthread_create (&th, NULL, tf, NULL) != 0) + { + puts ("create failed"); + exit (1); + } + + int e = pthread_barrier_wait (&bar); + if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) + { + puts ("1st barrier_wait failed"); + exit (1); + } + + if (pthread_cancel (th) != 0) + { + puts ("1st cancel failed"); + exit (1); + } + + void *r; + if (pthread_join (th, &r) != 0) + { + puts ("join failed"); + exit (1); + } + + if (r != PTHREAD_CANCELED) + { + puts ("thread not canceled"); + exit (1); + } + + return 0; +} + + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" |