t_cancellation.c revision 1.4 1 /* $NetBSD: t_cancellation.c,v 1.4 2025/04/05 11:22:32 riastradh Exp $ */
2
3 /*
4 * Copyright (c) 2025 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <sys/cdefs.h>
30 __RCSID("$NetBSD: t_cancellation.c,v 1.4 2025/04/05 11:22:32 riastradh Exp $");
31
32 #include <sys/event.h>
33 #include <sys/mman.h>
34 #include <sys/msg.h>
35 #include <sys/socket.h>
36 #include <sys/un.h>
37 #include <sys/wait.h>
38
39 #include <aio.h>
40 #include <atf-c.h>
41 #include <fcntl.h>
42 #include <mqueue.h>
43 #include <paths.h>
44 #include <poll.h>
45 #include <pthread.h>
46 #include <signal.h>
47 #include <stdatomic.h>
48 #include <string.h>
49 #include <termios.h>
50 #include <threads.h>
51 #include <time.h>
52 #include <unistd.h>
53
54 #include "cancelpoint.h"
55 #include "h_macros.h"
56
57 static const char *
58 c11thrd_err(int error)
59 {
60 static char buf[32];
61
62 switch (error) {
63 case thrd_busy: return "thrd_busy";
64 case thrd_nomem: return "thrd_nomem";
65 case thrd_success: return "thrd_success";
66 case thrd_timedout: return "thrd_timedout";
67 default:
68 snprintf(buf, sizeof(buf), "thrd_%d", error);
69 return buf;
70 }
71 }
72
73 #define RT(x) do \
74 { \
75 int RT_rv = (x); \
76 ATF_REQUIRE_MSG(RT_rv == 0, "%s: %d (%s)", \
77 #x, RT_rv, c11thrd_err(RT_rv)); \
78 } while (0)
79
80 pthread_barrier_t bar;
81 bool cleanup_done;
82
83 /* POSIX style */
84 static void *
85 emptythread(void *cookie)
86 {
87 return NULL;
88 }
89
90 /* C11 style */
91 static int
92 emptythrd(void *cookie)
93 {
94 return 123;
95 }
96
97 static void
98 cleanup_pthread_join(void *cookie)
99 {
100 pthread_t *tp = cookie;
101 void *result;
102
103 RZ(pthread_join(*tp, &result));
104 ATF_CHECK_MSG(result == NULL, "result=%p", result);
105 }
106
107 static void
108 cleanup_thrd_join(void *cookie)
109 {
110 thrd_t *tp = cookie;
111 int result;
112
113 RT(thrd_join(*tp, &result));
114 ATF_CHECK_MSG(result == 123, "result=%d", result);
115 }
116
117 static void
118 cleanup_msgid(void *cookie)
119 {
120 int *msgidp = cookie;
121
122 /*
123 * These message queue identifiers are persistent, so make sure
124 * to clean them up; otherwise the operator will have to run
125 * `ipcrm -q all' from time to time or else the tests will fail
126 * with ENOSPC.
127 */
128 RL(msgctl(*msgidp, IPC_RMID, NULL));
129 }
130
131 /*
132 * List of cancellation points in POSIX:
133 *
134 * https://pubs.opengroup.org/onlinepubs/9799919799.2024edition/functions/V2_chap02.html#tag_16_09_05_02
135 */
136
137 static int
138 acceptsetup(void)
139 {
140 struct sockaddr_un sun = { .sun_family = AF_LOCAL };
141 int sock;
142
143 strncpy(sun.sun_path, "sock", sizeof(sun.sun_path));
144 RL(sock = socket(PF_LOCAL, SOCK_STREAM, 0));
145 RL(bind(sock, (const struct sockaddr *)&sun, sizeof(sun)));
146 RL(listen(sock, 1));
147
148 return sock;
149 }
150
151 static void
152 cancelpoint_accept(void)
153 {
154 const int sock = acceptsetup();
155
156 cancelpointready();
157 RL(accept(sock, NULL, NULL));
158 }
159
160 static void
161 cancelpoint_accept4(void)
162 {
163 const int sock = acceptsetup();
164
165 cancelpointready();
166 RL(accept4(sock, NULL, NULL, O_CLOEXEC));
167 }
168
169 static void
170 cancelpoint_aio_suspend(void)
171 {
172 int fd[2];
173 char buf[32];
174 struct aiocb aio = {
175 .aio_offset = 0,
176 .aio_buf = buf,
177 .aio_nbytes = sizeof(buf),
178 .aio_fildes = -1,
179 };
180 const struct aiocb *const aiolist[] = { &aio };
181
182 RL(pipe(fd));
183 aio.aio_fildes = fd[0];
184 RL(aio_read(&aio));
185 cancelpointready();
186 RL(aio_suspend(aiolist, __arraycount(aiolist), NULL));
187 }
188
189 static void
190 cancelpoint_clock_nanosleep(void)
191 {
192 /* XXX test all CLOCK_*? */
193 struct timespec t = {.tv_sec = 1, .tv_nsec = 0};
194
195 cancelpointready();
196 RL(clock_nanosleep(CLOCK_MONOTONIC, 0, &t, NULL));
197 }
198
199 static void
200 cancelpoint_close(void)
201 {
202 int fd;
203
204 RL(fd = open("/dev/null", O_RDWR));
205 cancelpointready();
206 RL(close(fd));
207 }
208
209 static void
210 cancelpoint_cnd_timedwait(void)
211 {
212 cnd_t cnd;
213 mtx_t mtx;
214 struct timespec t = {.tv_sec = 1, .tv_nsec = 0};
215
216 RT(cnd_init(&cnd));
217 RT(mtx_init(&mtx, mtx_plain));
218 cancelpointready();
219 RT(mtx_lock(&mtx));
220 RT(cnd_timedwait(&cnd, &mtx, &t));
221 RT(mtx_unlock(&mtx));
222 }
223
224 static void
225 cancelpoint_cnd_wait(void)
226 {
227 cnd_t cnd;
228 mtx_t mtx;
229
230 RT(cnd_init(&cnd));
231 RT(mtx_init(&mtx, mtx_plain));
232 cancelpointready();
233 RT(mtx_lock(&mtx));
234 RT(cnd_wait(&cnd, &mtx));
235 RT(mtx_unlock(&mtx));
236 }
237
238 static void
239 cancelpoint_connect(void)
240 {
241 struct sockaddr_un sun = { .sun_family = AF_LOCAL };
242 int sock;
243
244 strncpy(sun.sun_path, "sock", sizeof(sun.sun_path));
245 RL(sock = socket(PF_LOCAL, SOCK_STREAM, 0));
246 cancelpointready();
247 RL(connect(sock, (const struct sockaddr *)&sun, sizeof(sun)));
248 }
249
250 static void
251 cancelpoint_creat(void)
252 {
253
254 cancelpointready();
255 RL(creat("file", 0666));
256 }
257
258 static void
259 cancelpoint_fcntl_F_SETLKW(void)
260 {
261 int fd;
262 struct flock fl = {
263 .l_start = 0,
264 .l_len = 0,
265 .l_type = F_WRLCK,
266 .l_whence = SEEK_SET,
267 };
268
269 RL(fd = open("file", O_RDWR|O_CREAT, 0666));
270 cancelpointready();
271 RL(fcntl(fd, F_SETLKW, &fl));
272 }
273
274 static void
275 cancelpoint_fcntl_F_OFD_SETLKW(void)
276 {
277 #ifdef F_OFD_SETLKW
278 int fd;
279 struct flock fl = {
280 .l_start = 0,
281 .l_len = 0,
282 .l_type = F_WRLCK,
283 .l_whence = SEEK_SET,
284 };
285
286 RL(fd = open("file", O_RDWR|O_CREAT, 0666));
287 cancelpointready();
288 RL(fcntl(fd, F_OFD_SETLKW, &fl));
289 #else
290 atf_tc_expect_fail("PR kern/59241: POSIX.1-2024:"
291 " OFD-owned file locks");
292 atf_tc_fail("no F_OFD_SETLKW");
293 #endif
294 }
295
296 static void
297 cancelpoint_fdatasync(void)
298 {
299 int fd;
300
301 RL(fd = open("file", O_RDWR|O_CREAT, 0666));
302 cancelpointready();
303 RL(fdatasync(fd));
304 }
305
306 static void
307 cancelpoint_fsync(void)
308 {
309 int fd;
310
311 RL(fd = open("file", O_RDWR|O_CREAT, 0666));
312 cancelpointready();
313 RL(fsync(fd));
314 }
315
316 static void
317 cancelpoint_kevent(void)
318 {
319 int kq;
320 struct kevent ev;
321
322 EV_SET(&ev, SIGUSR1, EVFILT_SIGNAL, EV_ADD|EV_ENABLE,
323 /*fflags*/0, /*data*/0, /*udata*/0);
324
325 RL(kq = kqueue());
326 RL(kevent(kq, &ev, 1, NULL, 1, &(const struct timespec){0,0}));
327 cancelpointready();
328 RL(kevent(kq, NULL, 0, &ev, 1, NULL));
329 }
330
331 static void
332 cancelpoint_lockf_F_LOCK(void)
333 {
334 int fd;
335
336 RL(fd = open("file", O_RDWR|O_CREAT, 0666));
337 cancelpointready();
338 RL(lockf(fd, F_LOCK, 0));
339 }
340
341 static void
342 cancelpoint_mq_receive(void)
343 {
344 mqd_t mq;
345 char buf[32];
346
347 RL(mq = mq_open("mq", O_RDWR|O_CREAT, 0666, NULL));
348 cancelpointready();
349 RL(mq_receive(mq, buf, sizeof(buf), NULL));
350 }
351
352 static void
353 cancelpoint_mq_send(void)
354 {
355 mqd_t mq;
356 char buf[32] = {0};
357
358 RL(mq = mq_open("mq", O_RDWR|O_CREAT, 0666, NULL));
359 cancelpointready();
360 RL(mq_send(mq, buf, sizeof(buf), 0));
361 }
362
363 static void
364 cancelpoint_mq_timedreceive(void)
365 {
366 mqd_t mq;
367 char buf[32];
368 struct timespec t = {.tv_sec = 1, .tv_nsec = 0};
369
370 RL(mq = mq_open("mq", O_RDWR|O_CREAT, 0666, NULL));
371 cancelpointready();
372 RL(mq_timedreceive(mq, buf, sizeof(buf), NULL, &t));
373 }
374
375 static void
376 cancelpoint_mq_timedsend(void)
377 {
378 mqd_t mq;
379 char buf[32] = {0};
380 struct timespec t = {.tv_sec = 1, .tv_nsec = 0};
381
382 RL(mq = mq_open("mq", O_RDWR|O_CREAT, 0666, NULL));
383 cancelpointready();
384 RL(mq_timedsend(mq, buf, sizeof(buf), 0, &t));
385 }
386
387 static void
388 cancelpoint_msgrcv(void)
389 {
390 int msgid;
391 char buf[32];
392
393 RL(msgid = msgget(IPC_PRIVATE, IPC_CREAT));
394 pthread_cleanup_push(&cleanup_msgid, &msgid);
395 cancelpointready();
396 RL(msgrcv(msgid, buf, sizeof(buf), 0, 0));
397 pthread_cleanup_pop(/*execute*/1);
398 }
399
400 static void
401 cancelpoint_msgsnd(void)
402 {
403 int msgid;
404 char buf[32] = {0};
405
406 RL(msgid = msgget(IPC_PRIVATE, IPC_CREAT));
407 pthread_cleanup_push(&cleanup_msgid, &msgid);
408 cancelpointready();
409 RL(msgsnd(msgid, buf, sizeof(buf), 0));
410 pthread_cleanup_pop(/*execute*/1);
411 }
412
413 static void
414 cancelpoint_msync(void)
415 {
416 const unsigned long pagesize = sysconf(_SC_PAGESIZE);
417 int fd;
418 void *map;
419
420 RL(fd = open("file", O_RDWR|O_CREAT, 0666));
421 RL(ftruncate(fd, pagesize));
422 REQUIRE_LIBC(map = mmap(NULL, pagesize, PROT_READ|PROT_WRITE,
423 MAP_SHARED, fd, 0),
424 MAP_FAILED);
425 cancelpointready();
426 RL(msync(map, pagesize, MS_SYNC));
427 }
428
429 static void
430 cancelpoint_nanosleep(void)
431 {
432 /* XXX test all CLOCK_*? */
433 struct timespec t = {.tv_sec = 1, .tv_nsec = 0};
434
435 cancelpointready();
436 RL(nanosleep(&t, NULL));
437 }
438
439 static void
440 cancelpoint_open(void)
441 {
442
443 cancelpointready();
444 RL(open("file", O_RDWR));
445 }
446
447 static void
448 cancelpoint_openat(void)
449 {
450
451 cancelpointready();
452 RL(openat(AT_FDCWD, "file", O_RDWR));
453 }
454
455 static void
456 cancelpoint_pause(void)
457 {
458
459 cancelpointready();
460 RL(pause());
461 }
462
463 static void
464 cancelpoint_poll(void)
465 {
466 int fd[2];
467 struct pollfd pfd;
468
469 RL(pipe(fd));
470 pfd.fd = fd[0];
471 pfd.events = POLLIN;
472 cancelpointready();
473 RL(poll(&pfd, 1, 1000));
474 }
475
476 static void
477 cancelpoint_posix_close(void)
478 {
479 #if 0
480 int fd;
481
482 RL(fd = open("file", O_RDWR|O_CREAT, 0666));
483 cancelpointready();
484 RL(posix_close(fd, POSIX_CLOSE_RESTART));
485 #else
486 atf_tc_expect_fail("PR kern/58929: POSIX.1-2024 compliance:"
487 " posix_close, POSIX_CLOSE_RESTART");
488 atf_tc_fail("no posix_close");
489 #endif
490 }
491
492 static void
493 cancelpoint_ppoll(void)
494 {
495 int fd[2];
496 struct pollfd pfd;
497 struct timespec t = {.tv_sec = 1, .tv_nsec = 0};
498
499 RL(pipe(fd));
500 pfd.fd = fd[0];
501 pfd.events = POLLIN;
502 cancelpointready();
503 RL(ppoll(&pfd, 1, &t, NULL));
504 }
505
506 static void
507 cancelpoint_pread(void)
508 {
509 int fd;
510 char buf[1];
511
512 RL(fd = open("file", O_RDWR|O_CREAT, 0666));
513 cancelpointready();
514 RL(pread(fd, buf, sizeof(buf), 1));
515 }
516
517
518 static void
519 cancelpoint_pselect(void)
520 {
521 int fd[2];
522 fd_set readfd;
523 struct timespec t = {.tv_sec = 1, .tv_nsec = 0};
524
525 FD_ZERO(&readfd);
526
527 RL(pipe(fd));
528 FD_SET(fd[0], &readfd);
529 cancelpointready();
530 RL(pselect(fd[0] + 1, &readfd, NULL, NULL, &t, NULL));
531 }
532
533 static void
534 cancelpoint_pthread_cond_clockwait(void)
535 {
536 #if 0
537 pthread_cond_t cond;
538 pthread_mutex_t mutex;
539 struct timespec t = {.tv_sec = 1, .tv_nsec = 0};
540
541 RZ(pthread_cond_init(&cond, NULL));
542 RZ(pthread_mutex_init(&mutex, NULL));
543 cancelpointready();
544 RZ(pthread_mutex_lock(&mutex));
545 RZ(pthread_cond_clockwait(&cond, &mutex, CLOCK_MONOTONIC, &t));
546 RZ(pthread_mutex_unlock(&mutex));
547 #else
548 atf_tc_expect_fail("PR lib/59142: POSIX.1-2024:"
549 " pthread_cond_clockwait and company");
550 atf_tc_fail("no posix_cond_clockwait");
551 #endif
552 }
553
554 static void
555 cancelpoint_pthread_cond_timedwait(void)
556 {
557 pthread_cond_t cond;
558 pthread_mutex_t mutex;
559 struct timespec t = {.tv_sec = 1, .tv_nsec = 0};
560
561 RZ(pthread_cond_init(&cond, NULL));
562 RZ(pthread_mutex_init(&mutex, NULL));
563 cancelpointready();
564 RZ(pthread_mutex_lock(&mutex));
565 RZ(pthread_cond_timedwait(&cond, &mutex, &t));
566 RZ(pthread_mutex_unlock(&mutex));
567 }
568
569 static void
570 cancelpoint_pthread_cond_wait(void)
571 {
572 pthread_cond_t cond;
573 pthread_mutex_t mutex;
574
575 RZ(pthread_cond_init(&cond, NULL));
576 RZ(pthread_mutex_init(&mutex, NULL));
577 cancelpointready();
578 RZ(pthread_mutex_lock(&mutex));
579 RZ(pthread_cond_wait(&cond, &mutex));
580 RZ(pthread_mutex_unlock(&mutex));
581 }
582
583 static void
584 cancelpoint_pthread_join(void)
585 {
586 pthread_t t;
587
588 RZ(pthread_create(&t, NULL, &emptythread, NULL));
589 pthread_cleanup_push(&cleanup_pthread_join, &t);
590 cancelpointready();
591 RZ(pthread_join(t, NULL));
592 pthread_cleanup_pop(/*execute*/0);
593 }
594
595 static void
596 cancelpoint_pthread_testcancel(void)
597 {
598
599 cancelpointready();
600 pthread_testcancel();
601 }
602
603 static void
604 cancelpoint_pwrite(void)
605 {
606 int fd;
607 char buf[1] = {0};
608
609 RL(fd = open("file", O_RDWR|O_CREAT, 0666));
610 cancelpointready();
611 RL(pwrite(fd, buf, sizeof(buf), 1));
612 }
613
614 static void
615 cancelpoint_read(void)
616 {
617 int fd;
618 char buf[1];
619
620 RL(fd = open("file", O_RDWR|O_CREAT, 0666));
621 cancelpointready();
622 RL(read(fd, buf, sizeof(buf)));
623 }
624
625 static void
626 cancelpoint_readv(void)
627 {
628 int fd;
629 char buf[1];
630 struct iovec iov = { .iov_base = buf, .iov_len = sizeof(buf) };
631
632 RL(fd = open("file", O_RDWR|O_CREAT, 0666));
633 cancelpointready();
634 RL(readv(fd, &iov, 1));
635 }
636
637 static void
638 cancelpoint_recv(void)
639 {
640 struct sockaddr_un sun = { .sun_family = AF_LOCAL };
641 int sock;
642 char buf[1];
643
644 strncpy(sun.sun_path, "sock", sizeof(sun.sun_path));
645 RL(sock = socket(PF_LOCAL, SOCK_DGRAM, 0));
646 RL(bind(sock, (const struct sockaddr *)&sun, sizeof(sun)));
647 cancelpointready();
648 RL(recv(sock, buf, sizeof(buf), 0));
649 }
650
651 static void
652 cancelpoint_recvfrom(void)
653 {
654 struct sockaddr_un sun = { .sun_family = AF_LOCAL };
655 int sock;
656 char buf[1];
657 struct sockaddr_storage ss;
658 socklen_t len = sizeof(ss);
659
660 strncpy(sun.sun_path, "sock", sizeof(sun.sun_path));
661 RL(sock = socket(PF_LOCAL, SOCK_DGRAM, 0));
662 RL(bind(sock, (const struct sockaddr *)&sun, sizeof(sun)));
663 cancelpointready();
664 RL(recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *)&ss, &len));
665 }
666
667 static void
668 cancelpoint_recvmsg(void)
669 {
670 struct sockaddr_un sun = { .sun_family = AF_LOCAL };
671 int sock;
672 char buf[1];
673 struct iovec iov = { .iov_base = buf, .iov_len = sizeof(buf) };
674 struct msghdr msg = {
675 .msg_iov = &iov,
676 .msg_iovlen = 1,
677 };
678
679 strncpy(sun.sun_path, "sock", sizeof(sun.sun_path));
680 RL(sock = socket(PF_LOCAL, SOCK_DGRAM, 0));
681 RL(bind(sock, (const struct sockaddr *)&sun, sizeof(sun)));
682 cancelpointready();
683 RL(recvmsg(sock, &msg, 0));
684 }
685
686 static void
687 cancelpoint_select(void)
688 {
689 int fd[2];
690 fd_set readfd;
691 struct timeval t = {.tv_sec = 1, .tv_usec = 0};
692
693 FD_ZERO(&readfd);
694
695 RL(pipe(fd));
696 FD_SET(fd[0], &readfd);
697 cancelpointready();
698 RL(select(fd[0] + 1, &readfd, NULL, NULL, &t));
699 }
700
701 static void
702 cancelpoint_send(void)
703 {
704 struct sockaddr_un sun = { .sun_family = AF_LOCAL };
705 int sock;
706 char buf[1] = {0};
707
708 strncpy(sun.sun_path, "sock", sizeof(sun.sun_path));
709 RL(sock = socket(PF_LOCAL, SOCK_DGRAM, 0));
710 RL(bind(sock, (const struct sockaddr *)&sun, sizeof(sun)));
711 cancelpointready();
712 RL(send(sock, buf, sizeof(buf), 0));
713 }
714
715 static void
716 cancelpoint_sendto(void)
717 {
718 struct sockaddr_un sun = { .sun_family = AF_LOCAL };
719 int sock;
720 char buf[1] = {0};
721
722 strncpy(sun.sun_path, "sock", sizeof(sun.sun_path));
723 RL(sock = socket(PF_LOCAL, SOCK_DGRAM, 0));
724 cancelpointready();
725 RL(sendto(sock, buf, sizeof(buf), 0, (const struct sockaddr *)&sun,
726 sizeof(sun)));
727 }
728
729 static void
730 cancelpoint_sendmsg(void)
731 {
732 struct sockaddr_un sun = { .sun_family = AF_LOCAL };
733 int sock;
734 char buf[1] = {0};
735 struct iovec iov = { .iov_base = buf, .iov_len = sizeof(buf) };
736 struct msghdr msg = {
737 .msg_name = (struct sockaddr *)&sun,
738 .msg_namelen = sizeof(sun),
739 .msg_iov = &iov,
740 .msg_iovlen = 1,
741 };
742
743 strncpy(sun.sun_path, "sock", sizeof(sun.sun_path));
744 RL(sock = socket(PF_LOCAL, SOCK_DGRAM, 0));
745 cancelpointready();
746 RL(sendmsg(sock, &msg, 0));
747 }
748
749 static void
750 cancelpoint_sigsuspend(void)
751 {
752 sigset_t mask, omask;
753
754 RL(sigfillset(&mask));
755 RL(sigprocmask(SIG_BLOCK, &mask, &omask));
756 cancelpointready();
757 RL(sigsuspend(&omask));
758 }
759
760 static void
761 cancelpoint_sigtimedwait(void)
762 {
763 sigset_t mask, omask;
764 siginfo_t info;
765 struct timespec t = {.tv_sec = 1, .tv_nsec = 0};
766
767 RL(sigfillset(&mask));
768 RL(sigprocmask(SIG_BLOCK, &mask, &omask));
769 cancelpointready();
770 RL(sigtimedwait(&omask, &info, &t));
771 }
772
773 static void
774 cancelpoint_sigwait(void)
775 {
776 sigset_t mask, omask;
777 int sig;
778
779 RL(sigfillset(&mask));
780 RL(sigprocmask(SIG_BLOCK, &mask, &omask));
781 cancelpointready();
782 RL(sigwait(&omask, &sig));
783 }
784
785 static void
786 cancelpoint_sigwaitinfo(void)
787 {
788 sigset_t mask, omask;
789 siginfo_t info;
790
791 RL(sigfillset(&mask));
792 RL(sigprocmask(SIG_BLOCK, &mask, &omask));
793 cancelpointready();
794 RL(sigwaitinfo(&omask, &info));
795 }
796
797 static void
798 cancelpoint_sleep(void)
799 {
800
801 cancelpointready();
802 (void)sleep(1);
803 }
804
805 static void
806 cancelpoint_tcdrain(void)
807 {
808 int hostfd, appfd;
809 char *pts;
810
811 RL(hostfd = posix_openpt(O_RDWR|O_NOCTTY));
812 RL(grantpt(hostfd));
813 RL(unlockpt(hostfd));
814 REQUIRE_LIBC(pts = ptsname(hostfd), NULL);
815 RL(appfd = open(pts, O_RDWR|O_NOCTTY));
816 cancelpointready();
817 RL(tcdrain(appfd));
818 }
819
820 static void
821 cancelpoint_thrd_join(void)
822 {
823 thrd_t t;
824
825 RT(thrd_create(&t, &emptythrd, NULL));
826 pthread_cleanup_push(&cleanup_thrd_join, &t);
827 cancelpointready();
828 RT(thrd_join(t, NULL));
829 pthread_cleanup_pop(/*execute*/0);
830 }
831
832 static void
833 cancelpoint_thrd_sleep(void)
834 {
835 struct timespec t = {.tv_sec = 1, .tv_nsec = 0};
836
837 cancelpointready();
838 RT(thrd_sleep(&t, NULL));
839 }
840
841 static void
842 cancelpoint_wait(void)
843 {
844
845 cancelpointready();
846 RL(wait(NULL));
847 }
848
849 static void
850 cancelpoint_waitid(void)
851 {
852
853 cancelpointready();
854 RL(waitid(P_ALL, 0, NULL, 0));
855 }
856
857 static void
858 cancelpoint_waitpid(void)
859 {
860
861 cancelpointready();
862 RL(waitpid(-1, NULL, 0));
863 }
864
865 static void
866 cancelpoint_write(void)
867 {
868 int fd;
869 char buf[1] = {0};
870
871 RL(fd = open("file", O_RDWR|O_CREAT, 0666));
872 cancelpointready();
873 RL(write(fd, buf, sizeof(buf)));
874 }
875
876 static void
877 cancelpoint_writev(void)
878 {
879 int fd;
880 char buf[1] = {0};
881 struct iovec iov = { .iov_base = buf, .iov_len = sizeof(buf) };
882
883 RL(fd = open("file", O_RDWR|O_CREAT, 0666));
884 cancelpointready();
885 RL(writev(fd, &iov, 1));
886 }
887
888 TEST_CANCELPOINT(cancelpoint_accept, __nothing)
889 TEST_CANCELPOINT(cancelpoint_accept4, __nothing)
890 TEST_CANCELPOINT(cancelpoint_aio_suspend, __nothing)
891 TEST_CANCELPOINT(cancelpoint_clock_nanosleep, __nothing)
892 TEST_CANCELPOINT(cancelpoint_close, __nothing)
893 TEST_CANCELPOINT(cancelpoint_cnd_timedwait, __nothing)
894 TEST_CANCELPOINT(cancelpoint_cnd_wait, __nothing)
895 TEST_CANCELPOINT(cancelpoint_connect, __nothing)
896 TEST_CANCELPOINT(cancelpoint_creat, __nothing)
897 TEST_CANCELPOINT(cancelpoint_fcntl_F_SETLKW, __nothing)
898 TEST_CANCELPOINT(cancelpoint_fcntl_F_OFD_SETLKW, __nothing)
899 TEST_CANCELPOINT(cancelpoint_fdatasync, __nothing)
900 TEST_CANCELPOINT(cancelpoint_fsync, __nothing)
901 TEST_CANCELPOINT(cancelpoint_kevent, __nothing)
902 TEST_CANCELPOINT(cancelpoint_lockf_F_LOCK, __nothing)
903 TEST_CANCELPOINT(cancelpoint_mq_receive, __nothing)
904 TEST_CANCELPOINT(cancelpoint_mq_send, __nothing)
905 TEST_CANCELPOINT(cancelpoint_mq_timedreceive, __nothing)
906 TEST_CANCELPOINT(cancelpoint_mq_timedsend, __nothing)
907 TEST_CANCELPOINT(cancelpoint_msgrcv, __nothing)
908 TEST_CANCELPOINT(cancelpoint_msgsnd, __nothing)
909 TEST_CANCELPOINT(cancelpoint_msync, __nothing)
910 TEST_CANCELPOINT(cancelpoint_nanosleep, __nothing)
911 TEST_CANCELPOINT(cancelpoint_open, __nothing)
912 TEST_CANCELPOINT(cancelpoint_openat, __nothing)
913 TEST_CANCELPOINT(cancelpoint_pause, __nothing)
914 TEST_CANCELPOINT(cancelpoint_poll, __nothing)
915 TEST_CANCELPOINT(cancelpoint_posix_close, __nothing)
916 TEST_CANCELPOINT(cancelpoint_ppoll, __nothing)
917 TEST_CANCELPOINT(cancelpoint_pread, __nothing)
918 TEST_CANCELPOINT(cancelpoint_pselect, __nothing)
919 TEST_CANCELPOINT(cancelpoint_pthread_cond_clockwait, __nothing)
920 TEST_CANCELPOINT(cancelpoint_pthread_cond_timedwait, __nothing)
921 TEST_CANCELPOINT(cancelpoint_pthread_cond_wait, __nothing)
922 TEST_CANCELPOINT(cancelpoint_pthread_join, __nothing)
923 TEST_CANCELPOINT(cancelpoint_pthread_testcancel, __nothing)
924 TEST_CANCELPOINT(cancelpoint_pwrite, __nothing)
925 TEST_CANCELPOINT(cancelpoint_read, __nothing)
926 TEST_CANCELPOINT(cancelpoint_readv, __nothing)
927 TEST_CANCELPOINT(cancelpoint_recv, __nothing)
928 TEST_CANCELPOINT(cancelpoint_recvfrom, __nothing)
929 TEST_CANCELPOINT(cancelpoint_recvmsg, __nothing)
930 TEST_CANCELPOINT(cancelpoint_select, __nothing)
931 TEST_CANCELPOINT(cancelpoint_send, __nothing)
932 TEST_CANCELPOINT(cancelpoint_sendto, __nothing)
933 TEST_CANCELPOINT(cancelpoint_sendmsg, __nothing)
934 TEST_CANCELPOINT(cancelpoint_sigsuspend, __nothing)
935 TEST_CANCELPOINT(cancelpoint_sigtimedwait, __nothing)
936 TEST_CANCELPOINT(cancelpoint_sigwait, __nothing)
937 TEST_CANCELPOINT(cancelpoint_sigwaitinfo, __nothing)
938 TEST_CANCELPOINT(cancelpoint_sleep, __nothing)
939 TEST_CANCELPOINT(cancelpoint_tcdrain, __nothing)
940 TEST_CANCELPOINT(cancelpoint_thrd_join, __nothing)
941 TEST_CANCELPOINT(cancelpoint_thrd_sleep, __nothing)
942 TEST_CANCELPOINT(cancelpoint_wait, __nothing)
943 TEST_CANCELPOINT(cancelpoint_waitid, __nothing)
944 TEST_CANCELPOINT(cancelpoint_waitpid, __nothing)
945 TEST_CANCELPOINT(cancelpoint_write, __nothing)
946 TEST_CANCELPOINT(cancelpoint_writev, __nothing)
947
948 ATF_TC(cleanuppop0);
949 ATF_TC_HEAD(cleanuppop0, tc)
950 {
951 atf_tc_set_md_var(tc, "descr", "Test pthread_cleanup_pop(0)");
952 }
953 ATF_TC_BODY(cleanuppop0, tc)
954 {
955
956 pthread_cleanup_push(&cleanup, &cleanup_done);
957 pthread_cleanup_pop(/*execute*/0);
958 ATF_CHECK(!cleanup_done);
959 }
960
961 ATF_TC(cleanuppop1);
962 ATF_TC_HEAD(cleanuppop1, tc)
963 {
964 atf_tc_set_md_var(tc, "descr", "Test pthread_cleanup_pop(1)");
965 }
966 ATF_TC_BODY(cleanuppop1, tc)
967 {
968
969 pthread_cleanup_push(&cleanup, &cleanup_done);
970 pthread_cleanup_pop(/*execute*/1);
971 ATF_CHECK(cleanup_done);
972 }
973
974 static void *
975 cancelself_async(void *cookie)
976 {
977 int *n = cookie;
978
979 RZ(pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL));
980
981 pthread_cleanup_push(&cleanup, &cleanup_done);
982
983 *n = 1;
984 RZ(pthread_cancel(pthread_self())); /* cancel */
985 *n = 2;
986 RZ(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL));
987 pthread_testcancel();
988 *n = 3;
989 RZ(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL));
990 pthread_testcancel();
991 *n = 4;
992
993 pthread_cleanup_pop(/*execute*/0);
994 return NULL;
995 }
996
997 ATF_TC(cancelself_async);
998 ATF_TC_HEAD(cancelself_async, tc)
999 {
1000 atf_tc_set_md_var(tc, "descr",
1001 "Test pthread_cancel(pthread_self()) async");
1002 }
1003 ATF_TC_BODY(cancelself_async, tc)
1004 {
1005 int n = 0;
1006 pthread_t t;
1007
1008 RZ(pthread_create(&t, NULL, &cancelself_async, &n));
1009
1010 alarm(1);
1011 RZ(pthread_join(t, NULL));
1012
1013 atf_tc_expect_fail("lib/59135: PTHREAD_CANCEL_ASYNCHRONOUS"
1014 " doesn't do much");
1015 ATF_CHECK_MSG(n == 1, "n=%d", n);
1016 atf_tc_expect_pass();
1017 ATF_CHECK(cleanup_done);
1018 }
1019
1020 static void *
1021 cancelself_deferred(void *cookie)
1022 {
1023 int *n = cookie;
1024
1025 /* PTHREAD_CANCEL_DEFERRED by default */
1026
1027 pthread_cleanup_push(&cleanup, &cleanup_done);
1028
1029 *n = 1;
1030 RZ(pthread_cancel(pthread_self()));
1031 *n = 2;
1032 RZ(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL));
1033 *n = 3;
1034 pthread_testcancel();
1035 *n = 4;
1036 RZ(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL));
1037 *n = 5;
1038 pthread_testcancel(); /* cancel */
1039 *n = 6;
1040
1041 pthread_cleanup_pop(/*execute*/0);
1042 return NULL;
1043 }
1044
1045 ATF_TC(cancelself_deferred);
1046 ATF_TC_HEAD(cancelself_deferred, tc)
1047 {
1048 atf_tc_set_md_var(tc, "descr",
1049 "Test pthread_cancel(pthread_self()) deferred");
1050 }
1051 ATF_TC_BODY(cancelself_deferred, tc)
1052 {
1053 int n = 0;
1054 pthread_t t;
1055
1056 RZ(pthread_create(&t, NULL, &cancelself_deferred, &n));
1057
1058 alarm(1);
1059 RZ(pthread_join(t, NULL));
1060
1061 ATF_CHECK_MSG(n == 5, "n=%d", n);
1062 ATF_CHECK(cleanup_done);
1063 }
1064
1065 static void *
1066 defaults(void *cookie)
1067 {
1068 int state, type;
1069
1070 fprintf(stderr, "created thread\n");
1071
1072 RZ(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &state));
1073 RZ(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &type));
1074
1075 ATF_CHECK_MSG(state == PTHREAD_CANCEL_ENABLE,
1076 "state=%d PTHREAD_CANCEL_ENABLE=%d PTHREAD_CANCEL_DISABLE=%d",
1077 state, PTHREAD_CANCEL_ENABLE, PTHREAD_CANCEL_DISABLE);
1078
1079 ATF_CHECK_MSG(type == PTHREAD_CANCEL_DEFERRED,
1080 "type=%d"
1081 " PTHREAD_CANCEL_DEFERRED=%d PTHREAD_CANCEL_ASYNCHRONOUS=%d",
1082 type, PTHREAD_CANCEL_DEFERRED, PTHREAD_CANCEL_ASYNCHRONOUS);
1083
1084 return NULL;
1085 }
1086
1087 ATF_TC(defaults);
1088 ATF_TC_HEAD(defaults, tc)
1089 {
1090 atf_tc_set_md_var(tc, "descr", "Test default cancelability");
1091 }
1092 ATF_TC_BODY(defaults, tc)
1093 {
1094 pthread_t t;
1095
1096 fprintf(stderr, "initial thread\n");
1097 (void)defaults(NULL);
1098
1099 RZ(pthread_create(&t, NULL, &defaults, NULL));
1100
1101 alarm(1);
1102 RZ(pthread_join(t, NULL));
1103 }
1104
1105 static void *
1106 disable_enable(void *cookie)
1107 {
1108 int *n = cookie;
1109
1110 pthread_cleanup_push(&cleanup, &cleanup_done);
1111
1112 *n = 1;
1113 pthread_testcancel();
1114 *n = 2;
1115 RZ(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL));
1116 *n = 3;
1117 (void)pthread_barrier_wait(&bar);
1118 *n = 4;
1119 pthread_testcancel();
1120 *n = 5;
1121 (void)pthread_barrier_wait(&bar);
1122 *n = 6;
1123 pthread_testcancel();
1124 *n = 7;
1125 RZ(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL));
1126 *n = 8;
1127 pthread_testcancel(); /* cancel */
1128 *n = 9;
1129
1130 pthread_cleanup_pop(/*execute*/0);
1131 return NULL;
1132 }
1133
1134 ATF_TC(disable_enable);
1135 ATF_TC_HEAD(disable_enable, tc)
1136 {
1137 atf_tc_set_md_var(tc, "descr",
1138 "Test disabling and re-enabling cancellation");
1139 }
1140 ATF_TC_BODY(disable_enable, tc)
1141 {
1142 int n = 0;
1143 pthread_t t;
1144
1145 RZ(pthread_barrier_init(&bar, NULL, 2));
1146
1147 RZ(pthread_create(&t, NULL, &disable_enable, &n));
1148
1149 (void)pthread_barrier_wait(&bar);
1150 RZ(pthread_cancel(t));
1151 (void)pthread_barrier_wait(&bar);
1152
1153 alarm(1);
1154 RZ(pthread_join(t, NULL));
1155
1156 ATF_CHECK_MSG(n == 8, "n=%d", n);
1157 ATF_CHECK(cleanup_done);
1158 }
1159
1160 static void *
1161 notestcancel_loop_async(void *cookie)
1162 {
1163
1164 RZ(pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL));
1165
1166 pthread_cleanup_push(&cleanup, &cleanup_done);
1167 (void)pthread_barrier_wait(&bar);
1168 for (;;)
1169 __insn_barrier();
1170 pthread_cleanup_pop(/*execute*/0);
1171
1172 return NULL;
1173 }
1174
1175 ATF_TC(notestcancel_loop_async);
1176 ATF_TC_HEAD(notestcancel_loop_async, tc)
1177 {
1178 atf_tc_set_md_var(tc, "descr",
1179 "Test nothing in a loop with PTHREAD_CANCEL_ASYNCHRONOUS");
1180 }
1181 ATF_TC_BODY(notestcancel_loop_async, tc)
1182 {
1183 pthread_t t;
1184 void *result;
1185
1186 RZ(pthread_barrier_init(&bar, NULL, 2));
1187 RZ(pthread_create(&t, NULL, ¬estcancel_loop_async, NULL));
1188
1189 (void)pthread_barrier_wait(&bar);
1190 RZ(pthread_cancel(t));
1191
1192 atf_tc_expect_signal(SIGALRM, "lib/59135: PTHREAD_CANCEL_ASYNCHRONOUS"
1193 " doesn't do much");
1194 alarm(1);
1195 RZ(pthread_join(t, &result));
1196 ATF_CHECK_MSG(result == PTHREAD_CANCELED,
1197 "result=%p PTHREAD_CANCELED=%p", result, PTHREAD_CANCELED);
1198 ATF_CHECK(cleanup_done);
1199 }
1200
1201 static void *
1202 disable_enable_async(void *cookie)
1203 {
1204 int *n = cookie;
1205
1206 pthread_cleanup_push(&cleanup, &cleanup_done);
1207
1208 RZ(pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL));
1209
1210 *n = 1;
1211 pthread_testcancel();
1212 *n = 2;
1213 RZ(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL));
1214 *n = 3;
1215 (void)pthread_barrier_wait(&bar);
1216 *n = 4;
1217 pthread_testcancel();
1218 *n = 5;
1219 (void)pthread_barrier_wait(&bar);
1220 *n = 6;
1221 pthread_testcancel();
1222 *n = 7;
1223 RZ(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL)); /* cancel */
1224 *n = 8;
1225 pthread_testcancel();
1226 *n = 9;
1227
1228 pthread_cleanup_pop(/*execute*/0);
1229 return NULL;
1230 }
1231
1232 ATF_TC(disable_enable_async);
1233 ATF_TC_HEAD(disable_enable_async, tc)
1234 {
1235 atf_tc_set_md_var(tc, "descr",
1236 "Test disabling and re-enabling cancellation when asynchronous");
1237 }
1238 ATF_TC_BODY(disable_enable_async, tc)
1239 {
1240 int n = 0;
1241 pthread_t t;
1242
1243 RZ(pthread_barrier_init(&bar, NULL, 2));
1244
1245 RZ(pthread_create(&t, NULL, &disable_enable_async, &n));
1246
1247 (void)pthread_barrier_wait(&bar);
1248 RZ(pthread_cancel(t));
1249 (void)pthread_barrier_wait(&bar);
1250
1251 alarm(1);
1252 RZ(pthread_join(t, NULL));
1253
1254 ATF_CHECK_MSG(n == 7, "n=%d", n);
1255 ATF_CHECK(cleanup_done);
1256 }
1257
1258 static void *
1259 disable_enable_setcanceltype_async(void *cookie)
1260 {
1261 int *n = cookie;
1262
1263 pthread_cleanup_push(&cleanup, &cleanup_done);
1264
1265 *n = 1;
1266 pthread_testcancel();
1267 *n = 2;
1268 RZ(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL));
1269 *n = 3;
1270 (void)pthread_barrier_wait(&bar);
1271 *n = 4;
1272 pthread_testcancel();
1273 *n = 5;
1274 (void)pthread_barrier_wait(&bar);
1275 *n = 6;
1276 pthread_testcancel();
1277 *n = 7;
1278 RZ(pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL));
1279 *n = 8;
1280 pthread_testcancel();
1281 *n = 9;
1282 RZ(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL)); /* cancel */
1283 *n = 10;
1284 pthread_testcancel();
1285 *n = 11;
1286
1287 pthread_cleanup_pop(/*execute*/0);
1288 return NULL;
1289 }
1290
1291 ATF_TC(disable_enable_setcanceltype_async);
1292 ATF_TC_HEAD(disable_enable_setcanceltype_async, tc)
1293 {
1294 atf_tc_set_md_var(tc, "descr",
1295 "Test disabling cancellation, setting it async, and re-enabling");
1296 }
1297 ATF_TC_BODY(disable_enable_setcanceltype_async, tc)
1298 {
1299 int n = 0;
1300 pthread_t t;
1301
1302 RZ(pthread_barrier_init(&bar, NULL, 2));
1303
1304 RZ(pthread_create(&t, NULL, &disable_enable_setcanceltype_async, &n));
1305
1306 (void)pthread_barrier_wait(&bar);
1307 RZ(pthread_cancel(t));
1308 (void)pthread_barrier_wait(&bar);
1309
1310 alarm(1);
1311 RZ(pthread_join(t, NULL));
1312
1313 ATF_CHECK_MSG(n == 9, "n=%d", n);
1314 ATF_CHECK(cleanup_done);
1315 }
1316
1317 static void *
1318 setcanceltype_async(void *cookie)
1319 {
1320 int *n = cookie;
1321
1322 pthread_cleanup_push(&cleanup, &cleanup_done);
1323
1324 *n = 1;
1325 pthread_testcancel();
1326 *n = 2;
1327 (void)pthread_barrier_wait(&bar);
1328 *n = 3;
1329 (void)pthread_barrier_wait(&bar);
1330 *n = 4;
1331 RZ(pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,
1332 NULL)); /* cancel */
1333 *n = 5;
1334
1335 pthread_cleanup_pop(/*execute*/0);
1336 return NULL;
1337 }
1338
1339 ATF_TC(setcanceltype_async);
1340 ATF_TC_HEAD(setcanceltype_async, tc)
1341 {
1342 atf_tc_set_md_var(tc, "descr",
1343 "Test disabling cancellation, setting it async, and re-enabling");
1344 }
1345 ATF_TC_BODY(setcanceltype_async, tc)
1346 {
1347 int n = 0;
1348 pthread_t t;
1349
1350 RZ(pthread_barrier_init(&bar, NULL, 2));
1351
1352 RZ(pthread_create(&t, NULL, &setcanceltype_async, &n));
1353
1354 (void)pthread_barrier_wait(&bar);
1355 RZ(pthread_cancel(t));
1356 (void)pthread_barrier_wait(&bar);
1357
1358 alarm(1);
1359 RZ(pthread_join(t, NULL));
1360
1361 ATF_CHECK_MSG(n == 4, "n=%d", n);
1362 ATF_CHECK(cleanup_done);
1363 }
1364
1365 static void
1366 sighandler(int signo)
1367 {
1368 int state;
1369
1370 RZ(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &state));
1371 RZ(pthread_setcancelstate(state, NULL));
1372 }
1373
1374 static void *
1375 sigsafecancelstate(void *cookie)
1376 {
1377 atomic_ulong *n = cookie;
1378 char name[128];
1379
1380 pthread_cleanup_push(&cleanup, &cleanup_done);
1381 REQUIRE_LIBC(signal(SIGUSR1, &sighandler), SIG_ERR);
1382
1383 (void)pthread_barrier_wait(&bar);
1384
1385 while (atomic_load_explicit(n, memory_order_relaxed) != 0) {
1386 /*
1387 * Do some things that might take the same lock as
1388 * pthread_setcancelstate.
1389 */
1390 RZ(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL));
1391 RZ(pthread_getname_np(pthread_self(), name, sizeof(name)));
1392 RZ(pthread_setname_np(pthread_self(), "%s", name));
1393 }
1394
1395 pthread_cleanup_pop(/*execute*/1);
1396 return NULL;
1397 }
1398
1399 ATF_TC(sigsafecancelstate);
1400 ATF_TC_HEAD(sigsafecancelstate, tc)
1401 {
1402 atf_tc_set_md_var(tc, "descr",
1403 "Test pthread_setcancelstate async-signal-safety");
1404 }
1405 ATF_TC_BODY(sigsafecancelstate, tc)
1406 {
1407 pthread_t t;
1408 atomic_ulong n = 10000;
1409 void *result;
1410
1411 RZ(pthread_barrier_init(&bar, NULL, 2));
1412 RZ(pthread_create(&t, NULL, &sigsafecancelstate, &n));
1413
1414 (void)pthread_barrier_wait(&bar);
1415
1416 while (atomic_load_explicit(&n, memory_order_relaxed)) {
1417 pthread_kill(t, SIGUSR1);
1418 atomic_store_explicit(&n,
1419 atomic_load_explicit(&n, memory_order_relaxed) - 1,
1420 memory_order_relaxed);
1421 }
1422
1423 alarm(1);
1424 RZ(pthread_join(t, &result));
1425 ATF_CHECK_MSG(result == NULL, "result=%p", result);
1426 ATF_CHECK(cleanup_done);
1427 }
1428
1429 static void *
1430 testcancel_loop(void *cookie)
1431 {
1432
1433 pthread_cleanup_push(&cleanup, &cleanup_done);
1434 (void)pthread_barrier_wait(&bar);
1435 for (;;)
1436 pthread_testcancel();
1437 pthread_cleanup_pop(/*execute*/0);
1438
1439 return NULL;
1440 }
1441
1442 ATF_TC(testcancel_loop);
1443 ATF_TC_HEAD(testcancel_loop, tc)
1444 {
1445 atf_tc_set_md_var(tc, "descr",
1446 "Test pthread_testcancel in a loop");
1447 }
1448 ATF_TC_BODY(testcancel_loop, tc)
1449 {
1450 pthread_t t;
1451 void *result;
1452
1453 RZ(pthread_barrier_init(&bar, NULL, 2));
1454 RZ(pthread_create(&t, NULL, &testcancel_loop, NULL));
1455
1456 (void)pthread_barrier_wait(&bar);
1457 RZ(pthread_cancel(t));
1458
1459 alarm(1);
1460 RZ(pthread_join(t, &result));
1461 ATF_CHECK_MSG(result == PTHREAD_CANCELED,
1462 "result=%p PTHREAD_CANCELED=%p", result, PTHREAD_CANCELED);
1463 ATF_CHECK(cleanup_done);
1464 }
1465
1466 ATF_TP_ADD_TCS(tp)
1467 {
1468
1469 ADD_TEST_CANCELPOINT(cancelpoint_accept);
1470 ADD_TEST_CANCELPOINT(cancelpoint_accept4);
1471 ADD_TEST_CANCELPOINT(cancelpoint_aio_suspend);
1472 ADD_TEST_CANCELPOINT(cancelpoint_clock_nanosleep);
1473 ADD_TEST_CANCELPOINT(cancelpoint_close);
1474 ADD_TEST_CANCELPOINT(cancelpoint_cnd_timedwait);
1475 ADD_TEST_CANCELPOINT(cancelpoint_cnd_wait);
1476 ADD_TEST_CANCELPOINT(cancelpoint_connect);
1477 ADD_TEST_CANCELPOINT(cancelpoint_creat);
1478 ADD_TEST_CANCELPOINT(cancelpoint_fcntl_F_SETLKW);
1479 ADD_TEST_CANCELPOINT(cancelpoint_fcntl_F_OFD_SETLKW);
1480 ADD_TEST_CANCELPOINT(cancelpoint_fdatasync);
1481 ADD_TEST_CANCELPOINT(cancelpoint_fsync);
1482 ADD_TEST_CANCELPOINT(cancelpoint_kevent);
1483 ADD_TEST_CANCELPOINT(cancelpoint_lockf_F_LOCK);
1484 ADD_TEST_CANCELPOINT(cancelpoint_mq_receive);
1485 ADD_TEST_CANCELPOINT(cancelpoint_mq_send);
1486 ADD_TEST_CANCELPOINT(cancelpoint_mq_timedreceive);
1487 ADD_TEST_CANCELPOINT(cancelpoint_mq_timedsend);
1488 ADD_TEST_CANCELPOINT(cancelpoint_msgrcv);
1489 ADD_TEST_CANCELPOINT(cancelpoint_msgsnd);
1490 ADD_TEST_CANCELPOINT(cancelpoint_msync);
1491 ADD_TEST_CANCELPOINT(cancelpoint_nanosleep);
1492 ADD_TEST_CANCELPOINT(cancelpoint_open);
1493 ADD_TEST_CANCELPOINT(cancelpoint_openat);
1494 ADD_TEST_CANCELPOINT(cancelpoint_pause);
1495 ADD_TEST_CANCELPOINT(cancelpoint_poll);
1496 ADD_TEST_CANCELPOINT(cancelpoint_posix_close);
1497 ADD_TEST_CANCELPOINT(cancelpoint_ppoll);
1498 ADD_TEST_CANCELPOINT(cancelpoint_pread);
1499 ADD_TEST_CANCELPOINT(cancelpoint_pselect);
1500 ADD_TEST_CANCELPOINT(cancelpoint_pthread_cond_clockwait);
1501 ADD_TEST_CANCELPOINT(cancelpoint_pthread_cond_timedwait);
1502 ADD_TEST_CANCELPOINT(cancelpoint_pthread_cond_wait);
1503 ADD_TEST_CANCELPOINT(cancelpoint_pthread_join);
1504 ADD_TEST_CANCELPOINT(cancelpoint_pthread_testcancel);
1505 ADD_TEST_CANCELPOINT(cancelpoint_pwrite);
1506 ADD_TEST_CANCELPOINT(cancelpoint_read);
1507 ADD_TEST_CANCELPOINT(cancelpoint_readv);
1508 ADD_TEST_CANCELPOINT(cancelpoint_recv);
1509 ADD_TEST_CANCELPOINT(cancelpoint_recvfrom);
1510 ADD_TEST_CANCELPOINT(cancelpoint_recvmsg);
1511 ADD_TEST_CANCELPOINT(cancelpoint_select);
1512 ADD_TEST_CANCELPOINT(cancelpoint_send);
1513 ADD_TEST_CANCELPOINT(cancelpoint_sendto);
1514 ADD_TEST_CANCELPOINT(cancelpoint_sendmsg);
1515 ADD_TEST_CANCELPOINT(cancelpoint_sigsuspend);
1516 ADD_TEST_CANCELPOINT(cancelpoint_sigtimedwait);
1517 ADD_TEST_CANCELPOINT(cancelpoint_sigwait);
1518 ADD_TEST_CANCELPOINT(cancelpoint_sigwaitinfo);
1519 ADD_TEST_CANCELPOINT(cancelpoint_sleep);
1520 ADD_TEST_CANCELPOINT(cancelpoint_tcdrain);
1521 ADD_TEST_CANCELPOINT(cancelpoint_thrd_join);
1522 ADD_TEST_CANCELPOINT(cancelpoint_thrd_sleep);
1523 ADD_TEST_CANCELPOINT(cancelpoint_wait);
1524 ADD_TEST_CANCELPOINT(cancelpoint_waitid);
1525 ADD_TEST_CANCELPOINT(cancelpoint_waitpid);
1526 ADD_TEST_CANCELPOINT(cancelpoint_write);
1527 ADD_TEST_CANCELPOINT(cancelpoint_writev);
1528
1529 ATF_TP_ADD_TC(tp, cleanuppop0);
1530 ATF_TP_ADD_TC(tp, cleanuppop1);
1531 ATF_TP_ADD_TC(tp, cancelself_async);
1532 ATF_TP_ADD_TC(tp, cancelself_deferred);
1533 ATF_TP_ADD_TC(tp, defaults);
1534 ATF_TP_ADD_TC(tp, disable_enable);
1535 ATF_TP_ADD_TC(tp, disable_enable_async);
1536 ATF_TP_ADD_TC(tp, disable_enable_setcanceltype_async);
1537 ATF_TP_ADD_TC(tp, setcanceltype_async);
1538 ATF_TP_ADD_TC(tp, notestcancel_loop_async);
1539 ATF_TP_ADD_TC(tp, sigsafecancelstate);
1540 ATF_TP_ADD_TC(tp, testcancel_loop);
1541
1542 return atf_no_error();
1543 }
1544