diff options
-rw-r--r-- | nptl/ChangeLog | 3 | ||||
-rw-r--r-- | nptl/Makefile | 4 | ||||
-rw-r--r-- | nptl/tst-cancel7.c | 209 |
3 files changed, 215 insertions, 1 deletions
diff --git a/nptl/ChangeLog b/nptl/ChangeLog index 2025464..fcc832f 100644 --- a/nptl/ChangeLog +++ b/nptl/ChangeLog @@ -1,5 +1,8 @@ 2003-01-04 Ulrich Drepper <drepper@redhat.com> + * Makefile (tests): Add tst-cancel7. + (tst-cancel7-ARGS): New variable. + * old_pthread_cond_broadcast.c: Optimize initialization a bit to work around gcc defficiencies. * old_pthread_cond_signal.c: Likewise. diff --git a/nptl/Makefile b/nptl/Makefile index a2d7abb..f181b4e 100644 --- a/nptl/Makefile +++ b/nptl/Makefile @@ -135,7 +135,7 @@ tests = tst-mutex1 tst-mutex2 tst-mutex3 tst-mutex4 tst-mutex5 tst-mutex6 \ tst-fork1 tst-fork2 tst-fork3 \ tst-atfork1 \ tst-cancel1 tst-cancel2 tst-cancel3 tst-cancel4 tst-cancel5 \ - tst-cancel6 \ + tst-cancel6 tst-cancel7 \ tst-cleanup1 \ tst-flock1 tst-flock2 \ tst-signal1 tst-signal2 tst-signal3 \ @@ -205,6 +205,8 @@ $(inst_libdir)/libpthread_nonshared.a: $(objpfx)libpthread_nonshared.a CFLAGS-tst-unload.c += -DPREFIX=\"$(objpfx)\" +tst-cancel7-ARGS = --command "$(built-program-cmd)" + extra-B-pthread.so = -B$(common-objpfx)nptl/ $(objpfx)libpthread.so: $(objpfx)crti.o $(objpfx)libpthread.so: +preinit += $(objpfx)crti.o diff --git a/nptl/tst-cancel7.c b/nptl/tst-cancel7.c new file mode 100644 index 0000000..50b4fde --- /dev/null +++ b/nptl/tst-cancel7.c @@ -0,0 +1,209 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <fcntl.h> +#include <pthread.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +const char *command; +const char *pidfile; +char pidfilename[] = "/tmp/tst-cancel7-XXXXXX"; + +static void * +tf (void *arg) +{ + const char *args = " --direct --pidfile "; + char *cmd = alloca (strlen (command) + strlen (args) + + strlen (pidfilename) + 1); + + strcpy (stpcpy (stpcpy (cmd, command), args), pidfilename); + system (cmd); + /* This call should never return. */ + return NULL; +} + + +static void +sl (void) +{ + FILE *f = fopen (pidfile, "w"); + if (f == NULL) + exit (1); + + fprintf (f, "%lld\n", (long long) getpid ()); + fflush (f); + + struct flock fl = + { + .l_type = F_WRLCK, + .l_start = 0, + .l_whence = SEEK_SET, + .l_len = 1 + }; + if (fcntl (fileno (f), F_SETLK, &fl) != 0) + exit (1); + + sigset_t ss; + sigfillset (&ss); + sigsuspend (&ss); + exit (0); +} + + +static void +do_prepare (int argc, char *argv[]) +{ + if (command == NULL) + command = argv[0]; + + if (pidfile) + sl (); + + int fd = mkstemp (pidfilename); + if (fd == -1) + { + puts ("mkstemp failed"); + exit (1); + } + + write (fd, " ", 1); + close (fd); +} + + +static int +do_test (void) +{ + pthread_t th; + if (pthread_create (&th, NULL, tf, NULL) != 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; + } + + sleep (1); + + FILE *f = fopen (pidfilename, "r+"); + if (f == NULL) + { + puts ("no pidfile"); + return 1; + } + + long long ll; + if (fscanf (f, "%lld\n", &ll) != 1) + { + puts ("could not read pid"); + unlink (pidfilename); + return 1; + } + + struct flock fl = + { + .l_type = F_WRLCK, + .l_start = 0, + .l_whence = SEEK_SET, + .l_len = 1 + }; + if (fcntl (fileno (f), F_GETLK, &fl) != 0) + { + puts ("F_GETLK failed"); + unlink (pidfilename); + return 1; + } + + if (fl.l_type != F_UNLCK) + { + printf ("child %lld still running\n", (long long) fl.l_pid); + if (fl.l_pid == ll) + kill (fl.l_pid, SIGKILL); + + unlink (pidfilename); + return 1; + } + + fclose (f); + + unlink (pidfilename); + + return r != PTHREAD_CANCELED; +} + +static void +do_cleanup (void) +{ + FILE *f = fopen (pidfilename, "r+"); + long long ll; + + if (f != NULL && fscanf (f, "%lld\n", &ll) == 1) + { + struct flock fl = + { + .l_type = F_WRLCK, + .l_start = 0, + .l_whence = SEEK_SET, + .l_len = 1 + }; + if (fcntl (fileno (f), F_GETLK, &fl) == 0 && fl.l_type != F_UNLCK + && fl.l_pid == ll) + kill (fl.l_pid, SIGKILL); + + fclose (f); + } + + unlink (pidfilename); +} + +#define OPT_COMMAND 10000 +#define OPT_PIDFILE 10001 +#define CMDLINE_OPTIONS \ + { "command", required_argument, NULL, OPT_COMMAND }, \ + { "pidfile", required_argument, NULL, OPT_PIDFILE }, +#define CMDLINE_PROCESS \ + case OPT_COMMAND: \ + command = optarg; \ + break; \ + case OPT_PIDFILE: \ + pidfile = optarg; \ + break; +// #define CLEANUP_HANDLER do_cleanup () +#define PREPARE(argc, argv) do_prepare (argc, argv) +#define TEST_FUNCTION do_test () +#define TIMEOUT 5 +#include "../test-skeleton.c" |