diff options
author | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2020-06-10 20:29:21 +0000 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2020-06-10 21:34:19 +0000 |
commit | 62d97c34320923f31380cb7851c81c5c9ce5284e (patch) | |
tree | 6f7c8ab2ba12547424894796eae9a683895811a0 /sysdeps/pthread | |
parent | bc9cf8fbe8eafe375719ad869ab81609cfc3529c (diff) | |
download | glibc-62d97c34320923f31380cb7851c81c5c9ce5284e.tar.gz glibc-62d97c34320923f31380cb7851c81c5c9ce5284e.tar.xz glibc-62d97c34320923f31380cb7851c81c5c9ce5284e.zip |
htl: Enable more cancel tests
* nptl/tst-cancel11.c, tst-cancel21-static.c, tst-cancel21.c, tst-cancel6.c, tst-cancelx11.c, tst-cancelx21.c, tst-cancelx6.c: Move to... * sysdeps/pthread: ... here. * nptl/Makefile: Move corresponding references and rules to... * sysdeps/pthread/Makefile: ... here.
Diffstat (limited to 'sysdeps/pthread')
-rw-r--r-- | sysdeps/pthread/Makefile | 17 | ||||
-rw-r--r-- | sysdeps/pthread/tst-cancel11.c | 122 | ||||
-rw-r--r-- | sysdeps/pthread/tst-cancel21-static.c | 1 | ||||
-rw-r--r-- | sysdeps/pthread/tst-cancel21.c | 298 | ||||
-rw-r--r-- | sysdeps/pthread/tst-cancel6.c | 78 | ||||
-rw-r--r-- | sysdeps/pthread/tst-cancelx11.c | 1 | ||||
-rw-r--r-- | sysdeps/pthread/tst-cancelx21.c | 1 | ||||
-rw-r--r-- | sysdeps/pthread/tst-cancelx6.c | 1 |
8 files changed, 513 insertions, 6 deletions
diff --git a/sysdeps/pthread/Makefile b/sysdeps/pthread/Makefile index 8d094b2221..a8e83d9d16 100644 --- a/sysdeps/pthread/Makefile +++ b/sysdeps/pthread/Makefile @@ -52,8 +52,10 @@ tests += tst-cnd-basic tst-mtx-trylock tst-cnd-broadcast \ tst-basic1 tst-basic2 tst-basic3 tst-basic4 tst-basic5 tst-basic6 \ tst-basic7 \ tst-cancel-self-canceltype tst-cancel-self-testcancel \ - tst-cancel1 tst-cancel2 tst-cancel3 tst-cancel8 tst-cancel10 \ + tst-cancel1 tst-cancel2 tst-cancel3 \ + tst-cancel6 tst-cancel8 tst-cancel10 tst-cancel11 \ tst-cancel12 tst-cancel14 tst-cancel15 tst-cancel18 tst-cancel19 \ + tst-cancel21 \ tst-cancel22 tst-cancel23 tst-cancel26 tst-cancel27 tst-cancel28 \ tst-cleanup0 tst-cleanup1 tst-cleanup2 tst-cleanup3 \ tst-clock1 \ @@ -113,8 +115,9 @@ tests-nolibpthread = tst-unload CFLAGS-tst-cleanup2.c += -fno-builtin CFLAGS-tst-cleanupx2.c += -fno-builtin -tests += tst-cancelx2 tst-cancelx3 tst-cancelx8 tst-cancelx10 \ - tst-cancelx12 tst-cancelx14 tst-cancelx15 tst-cancelx18 \ +tests += tst-cancelx2 tst-cancelx3 tst-cancelx6 tst-cancelx8 tst-cancelx10 \ + tst-cancelx11 tst-cancelx12 tst-cancelx14 tst-cancelx15 \ + tst-cancelx18 tst-cancelx21 \ tst-cleanupx0 tst-cleanupx1 tst-cleanupx2 tst-cleanupx3 ifeq ($(build-shared),yes) @@ -133,10 +136,9 @@ ifeq ($(build-shared),yes) tests: $(test-modules) endif -tests-static += tst-locale1 tst-locale2 - -tests += tst-cond11-static +tests-static += tst-locale1 tst-locale2 tst-cancel21-static \ +tests += tst-cancel21-static tst-cond11-static # These tests are linked with libc before libpthread tests-reverse += tst-cancel23 tst-vfork1x tst-vfork2x @@ -151,12 +153,15 @@ endif # implementation. For this we have to pass the -fexceptions parameter. CFLAGS-tst-cancelx2.c += -fexceptions CFLAGS-tst-cancelx3.c += -fexceptions +CFLAGS-tst-cancelx6.c += -fexceptions CFLAGS-tst-cancelx8.c += -fexceptions CFLAGS-tst-cancelx10.c += -fexceptions +CFLAGS-tst-cancelx11.c += -fexceptions CFLAGS-tst-cancelx12.c += -fexceptions CFLAGS-tst-cancelx14.c += -fexceptions CFLAGS-tst-cancelx15.c += -fexceptions CFLAGS-tst-cancelx18.c += -fexceptions +CFLAGS-tst-cancelx21.c += -fexceptions -fasynchronous-unwind-tables CFLAGS-tst-cleanupx0.c += -fexceptions -fasynchronous-unwind-tables CFLAGS-tst-cleanupx1.c += -fexceptions -fasynchronous-unwind-tables CFLAGS-tst-cleanupx2.c += -fexceptions diff --git a/sysdeps/pthread/tst-cancel11.c b/sysdeps/pthread/tst-cancel11.c new file mode 100644 index 0000000000..0859ff1bda --- /dev/null +++ b/sysdeps/pthread/tst-cancel11.c @@ -0,0 +1,122 @@ +/* Copyright (C) 2003-2020 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, see + <https://www.gnu.org/licenses/>. */ + +#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" diff --git a/sysdeps/pthread/tst-cancel21-static.c b/sysdeps/pthread/tst-cancel21-static.c new file mode 100644 index 0000000000..2a01061ea8 --- /dev/null +++ b/sysdeps/pthread/tst-cancel21-static.c @@ -0,0 +1 @@ +#include "tst-cancel21.c" diff --git a/sysdeps/pthread/tst-cancel21.c b/sysdeps/pthread/tst-cancel21.c new file mode 100644 index 0000000000..953c25e33a --- /dev/null +++ b/sysdeps/pthread/tst-cancel21.c @@ -0,0 +1,298 @@ +/* Copyright (C) 2003-2020 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@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, see + <https://www.gnu.org/licenses/>. */ + +#include <errno.h> +#include <pthread.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/wait.h> +#include <unistd.h> + + +static int fd[4]; +static pthread_barrier_t b; +volatile int in_sh_body; +unsigned long cleanups; + +static void +cl (void *arg) +{ + cleanups = (cleanups << 4) | (long) arg; +} + + +static void __attribute__((noinline)) +sh_body (void) +{ + char c; + + pthread_cleanup_push (cl, (void *) 1L); + + in_sh_body = 1; + if (read (fd[2], &c, 1) == 1) + { + puts ("read succeeded"); + exit (1); + } + + pthread_cleanup_pop (0); +} + + +static void +sh (int sig) +{ + pthread_cleanup_push (cl, (void *) 2L); + sh_body (); + in_sh_body = 0; + + pthread_cleanup_pop (0); +} + + +static void __attribute__((noinline)) +tf_body (void) +{ + char c; + + pthread_cleanup_push (cl, (void *) 3L); + + int r = pthread_barrier_wait (&b); + if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD) + { + puts ("child thread: barrier_wait failed"); + exit (1); + } + + if (read (fd[0], &c, 1) == 1) + { + puts ("read succeeded"); + exit (1); + } + + read (fd[0], &c, 1); + + pthread_cleanup_pop (0); +} + + +static void * +tf (void *arg) +{ + pthread_t th = (pthread_t) arg; + + int r = pthread_barrier_wait (&b); + if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD) + { + puts ("parent thread: barrier_wait failed"); + exit (1); + } + + sleep (1); + + r = pthread_kill (th, SIGHUP); + if (r) + { + errno = r; + printf ("pthread_kill failed %m\n"); + exit (1); + } + + while (in_sh_body == 0) + sleep (1); + + if (pthread_cancel (th) != 0) + { + puts ("cancel failed"); + exit (1); + } + + void *ret; + if (pthread_join (th, &ret) != 0) + { + puts ("join failed"); + exit (1); + } + + if (ret != PTHREAD_CANCELED) + { + puts ("result is wrong"); + exit (1); + } + + if (cleanups != 0x1234L) + { + printf ("called cleanups %lx\n", cleanups); + exit (1); + } + + if (pthread_barrier_destroy (&b)) + { + puts ("barrier destroy failed"); + exit (1); + } + + /* The pipe closing must be issued after the cancellation handling to avoid + a race condition where the cancellation runs after both pipe ends are + closed. In this case the read syscall returns EOF and the cancellation + must not act. */ + close (fd[0]); + close (fd[1]); + close (fd[2]); + close (fd[3]); + + exit (0); +} + + +static int +do_one_test (void) +{ + in_sh_body = 0; + + pid_t pid = fork (); + + if (pid == -1) + { + printf ("fork failed: %m\n"); + return 1; + } + + if (pid) + { + int status; + if (waitpid (pid, &status, 0) < 0) + { + printf ("waitpid failed %m\n"); + return 1; + } + + return !WIFEXITED (status) || WEXITSTATUS (status); + } + + if (pthread_barrier_init (&b, NULL, 2) != 0) + { + puts ("barrier_init failed"); + exit (1); + } + + cleanups = 0; + if (pipe (fd) != 0 || pipe (fd + 2) != 0) + { + puts ("pipe failed"); + exit (1); + } + + pthread_t th; + if (pthread_create (&th, NULL, tf, (void *) pthread_self ()) != 0) + { + puts ("create failed"); + exit (1); + } + + pthread_cleanup_push (cl, (void *) 4L); + tf_body (); + pthread_cleanup_pop (0); + exit (1); +} + + +static int +do_test (void) +{ + stack_t ss; + ss.ss_sp = malloc (2 * SIGSTKSZ); + if (ss.ss_sp == NULL) + { + puts ("failed to allocate alternate stack"); + return 1; + } + ss.ss_flags = 0; + ss.ss_size = 2 * SIGSTKSZ; + if (sigaltstack (&ss, NULL) < 0) + { + printf ("sigaltstack failed %m\n"); + return 1; + } + + struct sigaction sa; + sa.sa_handler = sh; + sigemptyset (&sa.sa_mask); + sa.sa_flags = 0; + + if (sigaction (SIGHUP, &sa, NULL) != 0) + { + puts ("sigaction failed"); + return 1; + } + + puts ("sa_flags = 0 test"); + if (do_one_test ()) + return 1; + + sa.sa_handler = sh; + sigemptyset (&sa.sa_mask); + sa.sa_flags = SA_ONSTACK; + + if (sigaction (SIGHUP, &sa, NULL) != 0) + { + puts ("sigaction failed"); + return 1; + } + + puts ("sa_flags = SA_ONSTACK test"); + if (do_one_test ()) + return 1; + +#ifdef SA_SIGINFO + sa.sa_sigaction = (void (*)(int, siginfo_t *, void *)) sh; + sigemptyset (&sa.sa_mask); + sa.sa_flags = SA_SIGINFO; + + if (sigaction (SIGHUP, &sa, NULL) != 0) + { + puts ("sigaction failed"); + return 1; + } + + puts ("sa_flags = SA_SIGINFO test"); + if (do_one_test ()) + return 1; + + sa.sa_sigaction = (void (*)(int, siginfo_t *, void *)) sh; + sigemptyset (&sa.sa_mask); + sa.sa_flags = SA_SIGINFO | SA_ONSTACK; + + if (sigaction (SIGHUP, &sa, NULL) != 0) + { + puts ("sigaction failed"); + return 1; + } + + puts ("sa_flags = SA_SIGINFO|SA_ONSTACK test"); + if (do_one_test ()) + return 1; +#endif + + return 0; +} + +#define TIMEOUT 40 +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/sysdeps/pthread/tst-cancel6.c b/sysdeps/pthread/tst-cancel6.c new file mode 100644 index 0000000000..c1beacf726 --- /dev/null +++ b/sysdeps/pthread/tst-cancel6.c @@ -0,0 +1,78 @@ +/* Copyright (C) 2002-2020 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + 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 + <https://www.gnu.org/licenses/>. */ + +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + + +static void * +tf (void *arg) +{ + char buf[100]; + fgets (buf, sizeof (buf), arg); + /* This call should never return. */ + return NULL; +} + + +static int +do_test (void) +{ + int fd[2]; + if (pipe (fd) != 0) + { + puts ("pipe failed"); + return 1; + } + + FILE *fp = fdopen (fd[0], "r"); + if (fp == NULL) + { + puts ("fdopen failed"); + return 1; + } + + pthread_t th; + if (pthread_create (&th, NULL, tf, fp) != 0) + { + puts ("pthread_create failed"); + return 1; + } + + sleep (1); + + if (pthread_cancel (th) != 0) + { + puts ("pthread_cancel failed"); + return 1; + } + + void *r; + if (pthread_join (th, &r) != 0) + { + puts ("pthread_join failed"); + return 1; + } + + return r != PTHREAD_CANCELED; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/sysdeps/pthread/tst-cancelx11.c b/sysdeps/pthread/tst-cancelx11.c new file mode 100644 index 0000000000..ffcc2eefc1 --- /dev/null +++ b/sysdeps/pthread/tst-cancelx11.c @@ -0,0 +1 @@ +#include "tst-cancel11.c" diff --git a/sysdeps/pthread/tst-cancelx21.c b/sysdeps/pthread/tst-cancelx21.c new file mode 100644 index 0000000000..2a01061ea8 --- /dev/null +++ b/sysdeps/pthread/tst-cancelx21.c @@ -0,0 +1 @@ +#include "tst-cancel21.c" diff --git a/sysdeps/pthread/tst-cancelx6.c b/sysdeps/pthread/tst-cancelx6.c new file mode 100644 index 0000000000..6926e21c2d --- /dev/null +++ b/sysdeps/pthread/tst-cancelx6.c @@ -0,0 +1 @@ +#include "tst-cancel6.c" |