1 /* Common file for all tst-cancel4_*
2 
3    Copyright (C) 2016-2021 Free Software Foundation, Inc.
4    This file is part of the GNU C Library.
5 
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
10 
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15 
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library; if not, see
18    <https://www.gnu.org/licenses/>.  */
19 
20 static int
do_test(void)21 do_test (void)
22 {
23   if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) != 0)
24     {
25       perror ("socketpair");
26       exit (1);
27     }
28 
29   set_socket_buffer (fds[1]);
30 
31   if (mktemp (fifoname) == NULL)
32     {
33       printf ("%s: cannot generate temp file name: %m\n", __func__);
34       exit (1);
35     }
36 
37   int result = 0;
38   size_t cnt;
39   for (cnt = 0; cnt < ntest_tf; ++cnt)
40     {
41       if (tests[cnt].only_early)
42 	continue;
43 
44       if (pthread_barrier_init (&b2, NULL, tests[cnt].nb) != 0)
45 	{
46 	  puts ("b2 init failed");
47 	  exit (1);
48 	}
49 
50       /* Reset the counter for the cleanup handler.  */
51       cl_called = 0;
52 
53       pthread_t th;
54       if (pthread_create (&th, NULL, tests[cnt].tf, NULL) != 0)
55 	{
56 	  printf ("create for '%s' test failed\n", tests[cnt].name);
57 	  result = 1;
58 	  continue;
59 	}
60 
61       int r = pthread_barrier_wait (&b2);
62       if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
63 	{
64 	  printf ("%s: barrier_wait failed\n", __func__);
65 	  result = 1;
66 	  continue;
67 	}
68 
69       struct timespec  ts = { .tv_sec = 0, .tv_nsec = 100000000 };
70       while (nanosleep (&ts, &ts) != 0)
71 	continue;
72 
73       if (pthread_cancel (th) != 0)
74 	{
75 	  printf ("cancel for '%s' failed\n", tests[cnt].name);
76 	  result = 1;
77 	  continue;
78 	}
79 
80       void *status;
81       if (pthread_join (th, &status) != 0)
82 	{
83 	  printf ("join for '%s' failed\n", tests[cnt].name);
84 	  result = 1;
85 	  continue;
86 	}
87       if (status != PTHREAD_CANCELED)
88 	{
89 	  printf ("thread for '%s' not canceled\n", tests[cnt].name);
90 	  result = 1;
91 	  continue;
92 	}
93 
94       if (pthread_barrier_destroy (&b2) != 0)
95 	{
96 	  puts ("barrier_destroy failed");
97 	  result = 1;
98 	  continue;
99 	}
100 
101       if (cl_called == 0)
102 	{
103 	  printf ("cleanup handler not called for '%s'\n", tests[cnt].name);
104 	  result = 1;
105 	  continue;
106 	}
107       if (cl_called > 1)
108 	{
109 	  printf ("cleanup handler called more than once for '%s'\n",
110 		  tests[cnt].name);
111 	  result = 1;
112 	  continue;
113 	}
114 
115       printf ("in-time cancel test of '%s' successful\n", tests[cnt].name);
116 
117       if (tempfd != -1)
118 	{
119 	  close (tempfd);
120 	  tempfd = -1;
121 	}
122       if (tempfd2 != -1)
123 	{
124 	  close (tempfd2);
125 	  tempfd2 = -1;
126 	}
127       if (tempfname != NULL)
128 	{
129 	  unlink (tempfname);
130 	  free (tempfname);
131 	  tempfname = NULL;
132 	}
133       if (tempmsg != -1)
134 	{
135 	  msgctl (tempmsg, IPC_RMID, NULL);
136 	  tempmsg = -1;
137 	}
138     }
139 
140   for (cnt = 0; cnt < ntest_tf; ++cnt)
141     {
142       if (pthread_barrier_init (&b2, NULL, tests[cnt].nb) != 0)
143 	{
144 	  puts ("b2 init failed");
145 	  exit (1);
146 	}
147 
148       /* Reset the counter for the cleanup handler.  */
149       cl_called = 0;
150 
151       pthread_t th;
152       if (pthread_create (&th, NULL, tests[cnt].tf, (void *) 1l) != 0)
153 	{
154 	  printf ("create for '%s' test failed\n", tests[cnt].name);
155 	  result = 1;
156 	  continue;
157 	}
158 
159       int r = pthread_barrier_wait (&b2);
160       if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
161 	{
162 	  printf ("%s: barrier_wait failed\n", __func__);
163 	  result = 1;
164 	  continue;
165 	}
166 
167       if (pthread_cancel (th) != 0)
168 	{
169 	  printf ("cancel for '%s' failed\n", tests[cnt].name);
170 	  result = 1;
171 	  continue;
172 	}
173 
174       r = pthread_barrier_wait (&b2);
175       if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
176 	{
177 	  printf ("%s: barrier_wait failed\n", __func__);
178 	  result = 1;
179 	  continue;
180 	}
181 
182       void *status;
183       if (pthread_join (th, &status) != 0)
184 	{
185 	  printf ("join for '%s' failed\n", tests[cnt].name);
186 	  result = 1;
187 	  continue;
188 	}
189       if (status != PTHREAD_CANCELED)
190 	{
191 	  printf ("thread for '%s' not canceled\n", tests[cnt].name);
192 	  result = 1;
193 	  continue;
194 	}
195 
196       if (pthread_barrier_destroy (&b2) != 0)
197 	{
198 	  puts ("barrier_destroy failed");
199 	  result = 1;
200 	  continue;
201 	}
202 
203       if (cl_called == 0)
204 	{
205 	  printf ("cleanup handler not called for '%s'\n", tests[cnt].name);
206 	  result = 1;
207 	  continue;
208 	}
209       if (cl_called > 1)
210 	{
211 	  printf ("cleanup handler called more than once for '%s'\n",
212 		  tests[cnt].name);
213 	  result = 1;
214 	  continue;
215 	}
216 
217       printf ("early cancel test of '%s' successful\n", tests[cnt].name);
218 
219       if (tempfd != -1)
220 	{
221 	  close (tempfd);
222 	  tempfd = -1;
223 	}
224       if (tempfd2 != -1)
225 	{
226 	  close (tempfd2);
227 	  tempfd2 = -1;
228 	}
229       if (tempfname != NULL)
230 	{
231 	  unlink (tempfname);
232 	  free (tempfname);
233 	  tempfname = NULL;
234 	}
235       if (tempmsg != -1)
236 	{
237 	  msgctl (tempmsg, IPC_RMID, NULL);
238 	  tempmsg = -1;
239 	}
240     }
241 
242   return result;
243 }
244 
245 #define TIMEOUT 60
246 #include <support/test-driver.c>
247