Back to index

glibc  2.9
tst-cancel7.c
Go to the documentation of this file.
00001 /* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003    Contributed by Jakub Jelinek <jakub@redhat.com>, 2002.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #include <errno.h>
00021 #include <fcntl.h>
00022 #include <pthread.h>
00023 #include <signal.h>
00024 #include <stdio.h>
00025 #include <stdlib.h>
00026 #include <string.h>
00027 #include <unistd.h>
00028 
00029 const char *command;
00030 const char *pidfile;
00031 char pidfilename[] = "/tmp/tst-cancel7-XXXXXX";
00032 
00033 static void *
00034 tf (void *arg)
00035 {
00036   const char *args = " --direct --pidfile ";
00037   char *cmd = alloca (strlen (command) + strlen (args)
00038                     + strlen (pidfilename) + 1);
00039 
00040   strcpy (stpcpy (stpcpy (cmd, command), args), pidfilename);
00041   system (cmd);
00042   /* This call should never return.  */
00043   return NULL;
00044 }
00045 
00046 
00047 static void
00048 sl (void)
00049 {
00050   FILE *f = fopen (pidfile, "w");
00051   if (f == NULL)
00052     exit (1);
00053 
00054   fprintf (f, "%lld\n", (long long) getpid ());
00055   fflush (f);
00056 
00057   struct flock fl =
00058     {
00059       .l_type = F_WRLCK,
00060       .l_start = 0,
00061       .l_whence = SEEK_SET,
00062       .l_len = 1
00063     };
00064   if (fcntl (fileno (f), F_SETLK, &fl) != 0)
00065     exit (1);
00066 
00067   sigset_t ss;
00068   sigfillset (&ss);
00069   sigsuspend (&ss);
00070   exit (0);
00071 }
00072 
00073 
00074 static void
00075 do_prepare (int argc, char *argv[])
00076 {
00077   if (command == NULL)
00078     command = argv[0];
00079 
00080   if (pidfile)
00081     sl ();
00082 
00083   int fd = mkstemp (pidfilename);
00084   if (fd == -1)
00085     {
00086       puts ("mkstemp failed");
00087       exit (1);
00088     }
00089 
00090   write (fd, " ", 1);
00091   close (fd);
00092 }
00093 
00094 
00095 static int
00096 do_test (void)
00097 {
00098   pthread_t th;
00099   if (pthread_create (&th, NULL, tf, NULL) != 0)
00100     {
00101       puts ("pthread_create failed");
00102       return 1;
00103     }
00104 
00105   do
00106     sleep (1);
00107   while (access (pidfilename, R_OK) != 0);
00108 
00109   if (pthread_cancel (th) != 0)
00110     {
00111       puts ("pthread_cancel failed");
00112       return 1;
00113     }
00114 
00115   void *r;
00116   if (pthread_join (th, &r) != 0)
00117     {
00118       puts ("pthread_join failed");
00119       return 1;
00120     }
00121 
00122   sleep (1);
00123 
00124   FILE *f = fopen (pidfilename, "r+");
00125   if (f == NULL)
00126     {
00127       puts ("no pidfile");
00128       return 1;
00129     }
00130 
00131   long long ll;
00132   if (fscanf (f, "%lld\n", &ll) != 1)
00133     {
00134       puts ("could not read pid");
00135       unlink (pidfilename);
00136       return 1;
00137     }
00138 
00139   struct flock fl =
00140     {
00141       .l_type = F_WRLCK,
00142       .l_start = 0,
00143       .l_whence = SEEK_SET,
00144       .l_len = 1
00145     };
00146   if (fcntl (fileno (f), F_GETLK, &fl) != 0)
00147     {
00148       puts ("F_GETLK failed");
00149       unlink (pidfilename);
00150       return 1;
00151     }
00152 
00153   if (fl.l_type != F_UNLCK)
00154     {
00155       printf ("child %lld still running\n", (long long) fl.l_pid);
00156       if (fl.l_pid == ll)
00157        kill (fl.l_pid, SIGKILL);
00158 
00159       unlink (pidfilename);
00160       return 1;
00161     }
00162 
00163   fclose (f);
00164 
00165   unlink (pidfilename);
00166 
00167   return r != PTHREAD_CANCELED;
00168 }
00169 
00170 static void
00171 do_cleanup (void)
00172 {
00173   FILE *f = fopen (pidfilename, "r+");
00174   long long ll;
00175 
00176   if (f != NULL && fscanf (f, "%lld\n", &ll) == 1)
00177     {
00178       struct flock fl =
00179        {
00180          .l_type = F_WRLCK,
00181          .l_start = 0,
00182          .l_whence = SEEK_SET,
00183          .l_len = 1
00184        };
00185       if (fcntl (fileno (f), F_GETLK, &fl) == 0 && fl.l_type != F_UNLCK
00186          && fl.l_pid == ll)
00187        kill (fl.l_pid, SIGKILL);
00188 
00189       fclose (f);
00190     }
00191 
00192   unlink (pidfilename);
00193 }
00194 
00195 #define OPT_COMMAND  10000
00196 #define OPT_PIDFILE  10001
00197 #define CMDLINE_OPTIONS \
00198   { "command", required_argument, NULL, OPT_COMMAND },  \
00199   { "pidfile", required_argument, NULL, OPT_PIDFILE },
00200 #define CMDLINE_PROCESS \
00201   case OPT_COMMAND:  \
00202     command = optarg;       \
00203     break;           \
00204   case OPT_PIDFILE:  \
00205     pidfile = optarg;       \
00206     break;
00207 // #define CLEANUP_HANDLER do_cleanup ()
00208 #define PREPARE(argc, argv) do_prepare (argc, argv)
00209 #define TEST_FUNCTION do_test ()
00210 #define TIMEOUT 5
00211 #include "../test-skeleton.c"