diff options
author | Ulrich Drepper <drepper@redhat.com> | 2003-01-05 04:58:18 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2003-01-05 04:58:18 +0000 |
commit | b74121ae4bc5fcedd4872353dac3af07b5e7eb0f (patch) | |
tree | 4465db85402528725bde66a4a6cfa3e33acfd3ce /nptl/tst-cancel7.c | |
parent | f0f9eb6ca3a08085f2e4db747f44afa6afed8969 (diff) | |
download | glibc-b74121ae4bc5fcedd4872353dac3af07b5e7eb0f.tar.gz glibc-b74121ae4bc5fcedd4872353dac3af07b5e7eb0f.tar.xz glibc-b74121ae4bc5fcedd4872353dac3af07b5e7eb0f.zip |
Update.
* Makefile (tests): Add tst-cancel7. (tst-cancel7-ARGS): New variable.
Diffstat (limited to 'nptl/tst-cancel7.c')
-rw-r--r-- | nptl/tst-cancel7.c | 209 |
1 files changed, 209 insertions, 0 deletions
diff --git a/nptl/tst-cancel7.c b/nptl/tst-cancel7.c new file mode 100644 index 0000000000..50b4fdec60 --- /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" |