]>
Commit | Line | Data |
---|---|---|
f7a9f785 | 1 | /* Copyright (C) 2003-2016 Free Software Foundation, Inc. |
1b6f6a92 UD |
2 | This file is part of the GNU C Library. |
3 | Contributed by Jakub Jelinek <jakub@redhat.com>, 2003. | |
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 | |
59ba27a6 PE |
16 | License along with the GNU C Library; if not, see |
17 | <http://www.gnu.org/licenses/>. */ | |
1b6f6a92 UD |
18 | |
19 | #include <errno.h> | |
20 | #include <error.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 <sys/select.h> | |
28 | #include <sys/time.h> | |
29 | #include <unistd.h> | |
30 | ||
31 | static void * | |
32 | tf (void *arg) | |
33 | { | |
34 | return NULL; | |
35 | } | |
36 | ||
37 | static void | |
38 | handler (int sig) | |
39 | { | |
40 | } | |
41 | ||
42 | static void __attribute__ ((noinline)) | |
43 | clobber_lots_of_regs (void) | |
44 | { | |
45 | #define X1(n) long r##n = 10##n; __asm __volatile ("" : "+r" (r##n)); | |
46 | #define X2(n) X1(n##0) X1(n##1) X1(n##2) X1(n##3) X1(n##4) | |
47 | #define X3(n) X2(n##0) X2(n##1) X2(n##2) X2(n##3) X2(n##4) | |
48 | X3(0) X3(1) X3(2) X3(3) X3(4) | |
49 | #undef X1 | |
50 | #define X1(n) __asm __volatile ("" : : "r" (r##n)); | |
51 | X3(0) X3(1) X3(2) X3(3) X3(4) | |
52 | #undef X1 | |
53 | #undef X2 | |
54 | #undef X3 | |
55 | } | |
56 | ||
57 | static int | |
58 | do_test (void) | |
59 | { | |
60 | pthread_t th; | |
61 | int old, rc; | |
62 | int ret = 0; | |
63 | int fd[2]; | |
64 | ||
65 | rc = pipe (fd); | |
66 | if (rc < 0) | |
67 | error (EXIT_FAILURE, errno, "couldn't create pipe"); | |
68 | ||
69 | rc = pthread_create (&th, NULL, tf, NULL); | |
70 | if (rc) | |
71 | error (EXIT_FAILURE, rc, "couldn't create thread"); | |
72 | ||
73 | rc = pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old); | |
74 | if (rc) | |
75 | { | |
76 | error (0, rc, "1st pthread_setcanceltype failed"); | |
77 | ret = 1; | |
78 | } | |
79 | if (old != PTHREAD_CANCEL_DEFERRED && old != PTHREAD_CANCEL_ASYNCHRONOUS) | |
80 | { | |
81 | error (0, 0, "1st pthread_setcanceltype returned invalid value %d", | |
82 | old); | |
83 | ret = 1; | |
84 | } | |
85 | ||
86 | clobber_lots_of_regs (); | |
87 | close (fd[0]); | |
88 | ||
89 | rc = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &old); | |
90 | if (rc) | |
91 | { | |
92 | error (0, rc, "pthread_setcanceltype after close failed"); | |
93 | ret = 1; | |
94 | } | |
95 | if (old != PTHREAD_CANCEL_DEFERRED) | |
96 | { | |
97 | error (0, 0, "pthread_setcanceltype after close returned invalid value %d", | |
98 | old); | |
99 | ret = 1; | |
100 | } | |
101 | ||
102 | clobber_lots_of_regs (); | |
103 | close (fd[1]); | |
104 | ||
105 | rc = pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old); | |
106 | if (rc) | |
107 | { | |
108 | error (0, rc, "pthread_setcanceltype after 2nd close failed"); | |
109 | ret = 1; | |
110 | } | |
111 | if (old != PTHREAD_CANCEL_ASYNCHRONOUS) | |
112 | { | |
113 | error (0, 0, "pthread_setcanceltype after 2nd close returned invalid value %d", | |
114 | old); | |
115 | ret = 1; | |
116 | } | |
117 | ||
118 | struct sigaction sa = { .sa_handler = handler, .sa_flags = 0 }; | |
119 | sigemptyset (&sa.sa_mask); | |
120 | sigaction (SIGALRM, &sa, NULL); | |
121 | ||
122 | struct itimerval it; | |
123 | it.it_value.tv_sec = 1; | |
124 | it.it_value.tv_usec = 0; | |
125 | it.it_interval = it.it_value; | |
126 | setitimer (ITIMER_REAL, &it, NULL); | |
127 | ||
128 | clobber_lots_of_regs (); | |
129 | pause (); | |
130 | ||
131 | memset (&it, 0, sizeof (it)); | |
132 | setitimer (ITIMER_REAL, &it, NULL); | |
133 | ||
134 | rc = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &old); | |
135 | if (rc) | |
136 | { | |
137 | error (0, rc, "pthread_setcanceltype after pause failed"); | |
138 | ret = 1; | |
139 | } | |
140 | if (old != PTHREAD_CANCEL_DEFERRED) | |
141 | { | |
142 | error (0, 0, "pthread_setcanceltype after pause returned invalid value %d", | |
143 | old); | |
144 | ret = 1; | |
145 | } | |
146 | ||
147 | it.it_value.tv_sec = 1; | |
148 | it.it_value.tv_usec = 0; | |
149 | it.it_interval = it.it_value; | |
150 | setitimer (ITIMER_REAL, &it, NULL); | |
151 | ||
152 | clobber_lots_of_regs (); | |
153 | pause (); | |
154 | ||
155 | memset (&it, 0, sizeof (it)); | |
156 | setitimer (ITIMER_REAL, &it, NULL); | |
157 | ||
158 | rc = pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old); | |
159 | if (rc) | |
160 | { | |
161 | error (0, rc, "pthread_setcanceltype after 2nd pause failed"); | |
162 | ret = 1; | |
163 | } | |
164 | if (old != PTHREAD_CANCEL_ASYNCHRONOUS) | |
165 | { | |
166 | error (0, 0, "pthread_setcanceltype after 2nd pause returned invalid value %d", | |
167 | old); | |
168 | ret = 1; | |
169 | } | |
170 | ||
171 | char fname[] = "/tmp/tst-cancel19-dir-XXXXXX\0foo/bar"; | |
172 | char *enddir = strchr (fname, '\0'); | |
173 | if (mkdtemp (fname) == NULL) | |
174 | { | |
175 | error (0, errno, "mkdtemp failed"); | |
176 | ret = 1; | |
177 | } | |
178 | *enddir = '/'; | |
179 | ||
180 | clobber_lots_of_regs (); | |
181 | creat (fname, 0400); | |
182 | ||
183 | rc = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &old); | |
184 | if (rc) | |
185 | { | |
186 | error (0, rc, "pthread_setcanceltype after creat failed"); | |
187 | ret = 1; | |
188 | } | |
189 | if (old != PTHREAD_CANCEL_DEFERRED) | |
190 | { | |
191 | error (0, 0, "pthread_setcanceltype after creat returned invalid value %d", | |
192 | old); | |
193 | ret = 1; | |
194 | } | |
195 | ||
196 | clobber_lots_of_regs (); | |
197 | creat (fname, 0400); | |
198 | ||
199 | rc = pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old); | |
200 | if (rc) | |
201 | { | |
202 | error (0, rc, "pthread_setcanceltype after 2nd creat failed"); | |
203 | ret = 1; | |
204 | } | |
205 | if (old != PTHREAD_CANCEL_ASYNCHRONOUS) | |
206 | { | |
207 | error (0, 0, "pthread_setcanceltype after 2nd creat returned invalid value %d", | |
208 | old); | |
209 | ret = 1; | |
210 | } | |
211 | ||
212 | clobber_lots_of_regs (); | |
213 | open (fname, O_CREAT, 0400); | |
214 | ||
215 | rc = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &old); | |
216 | if (rc) | |
217 | { | |
218 | error (0, rc, "pthread_setcanceltype after open failed"); | |
219 | ret = 1; | |
220 | } | |
221 | if (old != PTHREAD_CANCEL_DEFERRED) | |
222 | { | |
223 | error (0, 0, "pthread_setcanceltype after open returned invalid value %d", | |
224 | old); | |
225 | ret = 1; | |
226 | } | |
227 | ||
228 | clobber_lots_of_regs (); | |
229 | open (fname, O_CREAT, 0400); | |
230 | ||
231 | rc = pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old); | |
232 | if (rc) | |
233 | { | |
234 | error (0, rc, "pthread_setcanceltype after 2nd open failed"); | |
235 | ret = 1; | |
236 | } | |
237 | if (old != PTHREAD_CANCEL_ASYNCHRONOUS) | |
238 | { | |
239 | error (0, 0, "pthread_setcanceltype after 2nd open returned invalid value %d", | |
240 | old); | |
241 | ret = 1; | |
242 | } | |
243 | ||
244 | *enddir = '\0'; | |
245 | rmdir (fname); | |
246 | ||
247 | clobber_lots_of_regs (); | |
248 | select (-1, NULL, NULL, NULL, NULL); | |
249 | ||
250 | rc = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &old); | |
251 | if (rc) | |
252 | { | |
253 | error (0, rc, "pthread_setcanceltype after select failed"); | |
254 | ret = 1; | |
255 | } | |
256 | if (old != PTHREAD_CANCEL_DEFERRED) | |
257 | { | |
258 | error (0, 0, "pthread_setcanceltype after select returned invalid value %d", | |
259 | old); | |
260 | ret = 1; | |
261 | } | |
262 | ||
263 | clobber_lots_of_regs (); | |
264 | select (-1, NULL, NULL, NULL, NULL); | |
265 | ||
266 | rc = pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old); | |
267 | if (rc) | |
268 | { | |
269 | error (0, rc, "pthread_setcanceltype after 2nd select failed"); | |
270 | ret = 1; | |
271 | } | |
272 | if (old != PTHREAD_CANCEL_ASYNCHRONOUS) | |
273 | { | |
274 | error (0, 0, "pthread_setcanceltype after 2nd select returned invalid value %d", | |
275 | old); | |
276 | ret = 1; | |
277 | } | |
278 | ||
279 | pthread_join (th, NULL); | |
280 | ||
281 | return ret; | |
282 | } | |
283 | ||
284 | #define TIMEOUT 20 | |
285 | #define TEST_FUNCTION do_test () | |
286 | #include "../test-skeleton.c" |