OSDN Git Service

16cc47cff6423ad88625c5ed6b99e2506eb057fa
[uclinux-h8/uClibc.git] / test / nptl / tst-cancel7.c
1 /* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Jakub Jelinek <jakub@redhat.com>, 2002.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
19
20 #include <errno.h>
21 #include <fcntl.h>
22 #include <pthread.h>
23 #include <signal.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <unistd.h>
28
29 const char *command;
30 const char *pidfile;
31 char pidfilename[] = "/tmp/tst-cancel7-XXXXXX";
32
33 static void *
34 tf (void *arg)
35 {
36   const char *args = " --direct --pidfile ";
37   char *cmd = alloca (strlen (command) + strlen (args)
38                       + strlen (pidfilename) + 1);
39
40   strcpy (stpcpy (stpcpy (cmd, command), args), pidfilename);
41   system (cmd);
42   /* This call should never return.  */
43   return NULL;
44 }
45
46
47 static void
48 sl (void)
49 {
50   FILE *f = fopen (pidfile, "w");
51   if (f == NULL)
52     exit (1);
53
54   fprintf (f, "%lld\n", (long long) getpid ());
55   fflush (f);
56
57   struct flock fl =
58     {
59       .l_type = F_WRLCK,
60       .l_start = 0,
61       .l_whence = SEEK_SET,
62       .l_len = 1
63     };
64   if (fcntl (fileno (f), F_SETLK, &fl) != 0)
65     exit (1);
66
67   sigset_t ss;
68   sigfillset (&ss);
69   sigsuspend (&ss);
70   exit (0);
71 }
72
73
74 static void
75 do_prepare (int argc, char *argv[])
76 {
77   if (command == NULL)
78     command = argv[0];
79
80   if (pidfile)
81     sl ();
82
83   int fd = mkstemp (pidfilename);
84   if (fd == -1)
85     {
86       puts ("mkstemp failed");
87       exit (1);
88     }
89
90   write (fd, " ", 1);
91   close (fd);
92 }
93
94
95 static int
96 do_test (void)
97 {
98   pthread_t th;
99   if (pthread_create (&th, NULL, tf, NULL) != 0)
100     {
101       puts ("pthread_create failed");
102       return 1;
103     }
104
105   do
106     sleep (1);
107   while (access (pidfilename, R_OK) != 0);
108
109   if (pthread_cancel (th) != 0)
110     {
111       puts ("pthread_cancel failed");
112       return 1;
113     }
114
115   void *r;
116   if (pthread_join (th, &r) != 0)
117     {
118       puts ("pthread_join failed");
119       return 1;
120     }
121
122   sleep (1);
123
124   FILE *f = fopen (pidfilename, "r+");
125   if (f == NULL)
126     {
127       puts ("no pidfile");
128       return 1;
129     }
130
131   long long ll;
132   if (fscanf (f, "%lld\n", &ll) != 1)
133     {
134       puts ("could not read pid");
135       unlink (pidfilename);
136       return 1;
137     }
138
139   struct flock fl =
140     {
141       .l_type = F_WRLCK,
142       .l_start = 0,
143       .l_whence = SEEK_SET,
144       .l_len = 1
145     };
146   if (fcntl (fileno (f), F_GETLK, &fl) != 0)
147     {
148       puts ("F_GETLK failed");
149       unlink (pidfilename);
150       return 1;
151     }
152
153   if (fl.l_type != F_UNLCK)
154     {
155       printf ("child %lld still running\n", (long long) fl.l_pid);
156       if (fl.l_pid == ll)
157         kill (fl.l_pid, SIGKILL);
158
159       unlink (pidfilename);
160       return 1;
161     }
162
163   fclose (f);
164
165   unlink (pidfilename);
166
167   return r != PTHREAD_CANCELED;
168 }
169
170 #if 0 /* unused */
171 static void
172 do_cleanup (void)
173 {
174   FILE *f = fopen (pidfilename, "r+");
175   long long ll;
176
177   if (f != NULL && fscanf (f, "%lld\n", &ll) == 1)
178     {
179       struct flock fl =
180         {
181           .l_type = F_WRLCK,
182           .l_start = 0,
183           .l_whence = SEEK_SET,
184           .l_len = 1
185         };
186       if (fcntl (fileno (f), F_GETLK, &fl) == 0 && fl.l_type != F_UNLCK
187           && fl.l_pid == ll)
188         kill (fl.l_pid, SIGKILL);
189
190       fclose (f);
191     }
192
193   unlink (pidfilename);
194 }
195 #endif
196
197 #define OPT_COMMAND     10000
198 #define OPT_PIDFILE     10001
199 #define CMDLINE_OPTIONS \
200   { "command", required_argument, NULL, OPT_COMMAND },  \
201   { "pidfile", required_argument, NULL, OPT_PIDFILE },
202 #define CMDLINE_PROCESS \
203   case OPT_COMMAND:     \
204     command = optarg;   \
205     break;              \
206   case OPT_PIDFILE:     \
207     pidfile = optarg;   \
208     break;
209 // #define CLEANUP_HANDLER do_cleanup ()
210 #define PREPARE(argc, argv) do_prepare (argc, argv)
211 #define TEST_FUNCTION do_test ()
212 #define TIMEOUT 5
213 #include "../test-skeleton.c"