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