diff options
author | Ulrich Drepper <drepper@redhat.com> | 2006-08-13 01:56:09 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2006-08-13 01:56:09 +0000 |
commit | 22bb134c318365dbac664e46c193538c14bf3c42 (patch) | |
tree | 6ec10e5142ec9266baf7c0cca31bf7e766804263 /nptl/tst-join5.c | |
parent | 4c3f81d07ae921bb58def1f34c8758a77989b219 (diff) | |
download | glibc-22bb134c318365dbac664e46c193538c14bf3c42.tar glibc-22bb134c318365dbac664e46c193538c14bf3c42.tar.gz glibc-22bb134c318365dbac664e46c193538c14bf3c42.tar.bz2 glibc-22bb134c318365dbac664e46c193538c14bf3c42.zip |
[BZ #2843]
2006-08-12 Ulrich Drepper <drepper@redhat.com>
[BZ #2843]
* pthread_join.c (pthread_join): Account for self being canceled
when checking for deadlocks.
* tst-join5.c: Cleanups. Allow to be used in tst-join6.
(tf1): Don't print anything after pthread_join returns, this would be
another cancellation point.
(tf2): Likewise.
* tst-join6.c: New file.
* Makefile (tests): Add tst-join6.
Diffstat (limited to 'nptl/tst-join5.c')
-rw-r--r-- | nptl/tst-join5.c | 115 |
1 files changed, 91 insertions, 24 deletions
diff --git a/nptl/tst-join5.c b/nptl/tst-join5.c index 589fac6b5f..db005f5b71 100644 --- a/nptl/tst-join5.c +++ b/nptl/tst-join5.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2003 Free Software Foundation, Inc. +/* Copyright (C) 2003, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2003. @@ -21,120 +21,187 @@ #include <pthread.h> #include <stdio.h> #include <stdlib.h> +#include <time.h> +#include <unistd.h> +#include <sys/syscall.h> + + +#define wait_code() \ + do { \ + struct timespec ts = { .tv_sec = 0, .tv_nsec = 200000000 }; \ + while (syscall (__NR_nanosleep, &ts, &ts) < 0) \ + /* nothing */; \ + } while (0) + + +#ifdef WAIT_IN_CHILD +static pthread_barrier_t b; +#endif static void * tf1 (void *arg) { - pthread_join ((pthread_t) arg, NULL); +#ifdef WAIT_IN_CHILD + int e = pthread_barrier_wait (&b); + if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) + { + printf ("%s: barrier_wait failed\n", __func__); + exit (1); + } - puts ("1st join returned"); + wait_code (); +#endif - return (void *) 1l; + pthread_join ((pthread_t) arg, NULL); + + exit (42); } static void * tf2 (void *arg) { - pthread_join ((pthread_t) arg, NULL); +#ifdef WAIT_IN_CHILD + int e = pthread_barrier_wait (&b); + if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) + { + printf ("%s: barrier_wait failed\n", __func__); + exit (1); + } - puts ("2nd join returned"); + wait_code (); +#endif + pthread_join ((pthread_t) arg, NULL); - return (void *) 1l; + exit (43); } static int do_test (void) { +#ifdef WAIT_IN_CHILD + if (pthread_barrier_init (&b, NULL, 2) != 0) + { + puts ("barrier_init failed"); + return 1; + } +#endif + pthread_t th; int err = pthread_join (pthread_self (), NULL); if (err == 0) { puts ("1st circular join succeeded"); - exit (1); + return 1; } if (err != EDEADLK) { printf ("1st circular join %d, not EDEADLK\n", err); - exit (1); + return 1; } if (pthread_create (&th, NULL, tf1, (void *) pthread_self ()) != 0) { puts ("1st create failed"); - exit (1); + return 1; } +#ifndef WAIT_IN_CHILD + wait_code (); +#endif + if (pthread_cancel (th) != 0) { puts ("cannot cancel 1st thread"); - exit (1); + return 1; + } + +#ifdef WAIT_IN_CHILD + int e = pthread_barrier_wait (&b); + if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) + { + printf ("%s: barrier_wait failed\n", __func__); + return 1; } +#endif void *r; err = pthread_join (th, &r); if (err != 0) { printf ("cannot join 1st thread: %d\n", err); - exit (1); + return 1; } if (r != PTHREAD_CANCELED) { puts ("1st thread not canceled"); - exit (1); + return 1; } err = pthread_join (pthread_self (), NULL); if (err == 0) { puts ("2nd circular join succeeded"); - exit (1); + return 1; } if (err != EDEADLK) { printf ("2nd circular join %d, not EDEADLK\n", err); - exit (1); + return 1; } if (pthread_create (&th, NULL, tf2, (void *) pthread_self ()) != 0) { puts ("2nd create failed"); - exit (1); + return 1; } +#ifndef WAIT_IN_CHILD + wait_code (); +#endif + if (pthread_cancel (th) != 0) { puts ("cannot cancel 2nd thread"); - exit (1); + return 1; } +#ifdef WAIT_IN_CHILD + e = pthread_barrier_wait (&b); + if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) + { + printf ("%s: barrier_wait failed\n", __func__); + return 1; + } +#endif + if (pthread_join (th, &r) != 0) { puts ("cannot join 2nd thread"); - exit (1); + return 1; } if (r != PTHREAD_CANCELED) { puts ("2nd thread not canceled"); - exit (1); + return 1; } err = pthread_join (pthread_self (), NULL); if (err == 0) { - puts ("2nd circular join succeeded"); - exit (1); + puts ("3rd circular join succeeded"); + return 1; } if (err != EDEADLK) { - printf ("2nd circular join %d, not EDEADLK\n", err); - exit (1); + printf ("3rd circular join %d, not EDEADLK\n", err); + return 1; } - exit (0); + return 0; } #define TEST_FUNCTION do_test () |