t_cancellation.c revision 1.1 1 /* $NetBSD: t_cancellation.c,v 1.1 2025/03/31 13:57:06 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.1 2025/03/31 13:57:06 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,
965 atf_tc_expect_signal(SIGALRM,
966 "PR lib/59240: POSIX.1-2024: cancellation point audit"))
967 TEST_CANCELPOINT(cancelpoint_aio_suspend, __nothing)
968 TEST_CANCELPOINT(cancelpoint_clock_nanosleep, __nothing)
969 TEST_CANCELPOINT(cancelpoint_close, __nothing)
970 TEST_CANCELPOINT(cancelpoint_cnd_timedwait, __nothing)
971 TEST_CANCELPOINT(cancelpoint_cnd_wait, __nothing)
972 TEST_CANCELPOINT(cancelpoint_connect, __nothing)
973 TEST_CANCELPOINT(cancelpoint_creat, __nothing)
974 TEST_CANCELPOINT(cancelpoint_fcntl_F_SETLKW, __nothing)
975 TEST_CANCELPOINT(cancelpoint_fcntl_F_OFD_SETLKW, __nothing)
976 TEST_CANCELPOINT(cancelpoint_fdatasync, __nothing)
977 TEST_CANCELPOINT(cancelpoint_fsync, __nothing)
978 TEST_CANCELPOINT(cancelpoint_lockf_F_LOCK, __nothing)
979 TEST_CANCELPOINT(cancelpoint_mq_receive, __nothing)
980 TEST_CANCELPOINT(cancelpoint_mq_send, __nothing)
981 TEST_CANCELPOINT(cancelpoint_mq_timedreceive, __nothing)
982 TEST_CANCELPOINT(cancelpoint_mq_timedsend, __nothing)
983 TEST_CANCELPOINT(cancelpoint_msgrcv, __nothing)
984 TEST_CANCELPOINT(cancelpoint_msgsnd, __nothing)
985 TEST_CANCELPOINT(cancelpoint_msync, __nothing)
986 TEST_CANCELPOINT(cancelpoint_nanosleep, __nothing)
987 TEST_CANCELPOINT(cancelpoint_open, __nothing)
988 TEST_CANCELPOINT(cancelpoint_openat, __nothing)
989 TEST_CANCELPOINT(cancelpoint_pause, __nothing)
990 TEST_CANCELPOINT(cancelpoint_poll, __nothing)
991 TEST_CANCELPOINT(cancelpoint_posix_close, __nothing)
992 TEST_CANCELPOINT(cancelpoint_ppoll, __nothing)
993 TEST_CANCELPOINT(cancelpoint_pread, __nothing)
994 TEST_CANCELPOINT(cancelpoint_pselect, __nothing)
995 TEST_CANCELPOINT(cancelpoint_pthread_cond_clockwait, __nothing)
996 TEST_CANCELPOINT(cancelpoint_pthread_cond_timedwait, __nothing)
997 TEST_CANCELPOINT(cancelpoint_pthread_cond_wait, __nothing)
998 TEST_CANCELPOINT(cancelpoint_pthread_join, __nothing)
999 TEST_CANCELPOINT(cancelpoint_pthread_testcancel, __nothing)
1000 TEST_CANCELPOINT(cancelpoint_pwrite, __nothing)
1001 TEST_CANCELPOINT(cancelpoint_read, __nothing)
1002 TEST_CANCELPOINT(cancelpoint_readv, __nothing)
1003 TEST_CANCELPOINT(cancelpoint_recv, __nothing)
1004 TEST_CANCELPOINT(cancelpoint_recvfrom, __nothing)
1005 TEST_CANCELPOINT(cancelpoint_recvmsg, __nothing)
1006 TEST_CANCELPOINT(cancelpoint_select, __nothing)
1007 TEST_CANCELPOINT(cancelpoint_send, __nothing)
1008 TEST_CANCELPOINT(cancelpoint_sendto, __nothing)
1009 TEST_CANCELPOINT(cancelpoint_sendmsg, __nothing)
1010 TEST_CANCELPOINT(cancelpoint_sigsuspend, __nothing)
1011 TEST_CANCELPOINT(cancelpoint_sigtimedwait, __nothing)
1012 TEST_CANCELPOINT(cancelpoint_sigwait, __nothing)
1013 TEST_CANCELPOINT(cancelpoint_sigwaitinfo, __nothing)
1014 TEST_CANCELPOINT(cancelpoint_sleep, __nothing)
1015 TEST_CANCELPOINT(cancelpoint_tcdrain,
1016 atf_tc_expect_fail("PR lib/59240: POSIX.1-2024: cancellation point audit"))
1017 TEST_CANCELPOINT(cancelpoint_thrd_join, __nothing)
1018 TEST_CANCELPOINT(cancelpoint_thrd_sleep, __nothing)
1019 TEST_CANCELPOINT(cancelpoint_wait, __nothing)
1020 TEST_CANCELPOINT(cancelpoint_waitid, __nothing)
1021 TEST_CANCELPOINT(cancelpoint_waitpid, __nothing)
1022 TEST_CANCELPOINT(cancelpoint_write, __nothing)
1023 TEST_CANCELPOINT(cancelpoint_writev, __nothing)
1024
1025 ATF_TC(cleanuppop0);
1026 ATF_TC_HEAD(cleanuppop0, tc)
1027 {
1028 atf_tc_set_md_var(tc, "descr", "Test pthread_cleanup_pop(0)");
1029 }
1030 ATF_TC_BODY(cleanuppop0, tc)
1031 {
1032
1033 pthread_cleanup_push(&cleanup, &cleanup_done);
1034 pthread_cleanup_pop(/*execute*/0);
1035 ATF_CHECK(!cleanup_done);
1036 }
1037
1038 ATF_TC(cleanuppop1);
1039 ATF_TC_HEAD(cleanuppop1, tc)
1040 {
1041 atf_tc_set_md_var(tc, "descr", "Test pthread_cleanup_pop(1)");
1042 }
1043 ATF_TC_BODY(cleanuppop1, tc)
1044 {
1045
1046 pthread_cleanup_push(&cleanup, &cleanup_done);
1047 pthread_cleanup_pop(/*execute*/1);
1048 ATF_CHECK(cleanup_done);
1049 }
1050
1051 static void *
1052 cancelself_async(void *cookie)
1053 {
1054 int *n = cookie;
1055
1056 RZ(pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL));
1057
1058 pthread_cleanup_push(&cleanup, &cleanup_done);
1059
1060 *n = 1;
1061 RZ(pthread_cancel(pthread_self())); /* cancel */
1062 *n = 2;
1063 RZ(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL));
1064 pthread_testcancel();
1065 *n = 3;
1066 RZ(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL));
1067 pthread_testcancel();
1068 *n = 4;
1069
1070 pthread_cleanup_pop(/*execute*/0);
1071 return NULL;
1072 }
1073
1074 ATF_TC(cancelself_async);
1075 ATF_TC_HEAD(cancelself_async, tc)
1076 {
1077 atf_tc_set_md_var(tc, "descr",
1078 "Test pthread_cancel(pthread_self()) async");
1079 }
1080 ATF_TC_BODY(cancelself_async, tc)
1081 {
1082 int n = 0;
1083 pthread_t t;
1084
1085 RZ(pthread_create(&t, NULL, &cancelself_async, &n));
1086
1087 alarm(1);
1088 RZ(pthread_join(t, NULL));
1089
1090 atf_tc_expect_fail("lib/59135: PTHREAD_CANCEL_ASYNCHRONOUS"
1091 " doesn't do much");
1092 ATF_CHECK_MSG(n == 1, "n=%d", n);
1093 atf_tc_expect_pass();
1094 ATF_CHECK(cleanup_done);
1095 }
1096
1097 static void *
1098 cancelself_deferred(void *cookie)
1099 {
1100 int *n = cookie;
1101
1102 /* PTHREAD_CANCEL_DEFERRED by default */
1103
1104 pthread_cleanup_push(&cleanup, &cleanup_done);
1105
1106 *n = 1;
1107 RZ(pthread_cancel(pthread_self()));
1108 *n = 2;
1109 RZ(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL));
1110 *n = 3;
1111 pthread_testcancel();
1112 *n = 4;
1113 RZ(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL));
1114 *n = 5;
1115 pthread_testcancel(); /* cancel */
1116 *n = 6;
1117
1118 pthread_cleanup_pop(/*execute*/0);
1119 return NULL;
1120 }
1121
1122 ATF_TC(cancelself_deferred);
1123 ATF_TC_HEAD(cancelself_deferred, tc)
1124 {
1125 atf_tc_set_md_var(tc, "descr",
1126 "Test pthread_cancel(pthread_self()) deferred");
1127 }
1128 ATF_TC_BODY(cancelself_deferred, tc)
1129 {
1130 int n = 0;
1131 pthread_t t;
1132
1133 RZ(pthread_create(&t, NULL, &cancelself_deferred, &n));
1134
1135 alarm(1);
1136 RZ(pthread_join(t, NULL));
1137
1138 ATF_CHECK_MSG(n == 5, "n=%d", n);
1139 ATF_CHECK(cleanup_done);
1140 }
1141
1142 static void *
1143 defaults(void *cookie)
1144 {
1145 int state, type;
1146
1147 fprintf(stderr, "created thread\n");
1148
1149 RZ(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &state));
1150 RZ(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &type));
1151
1152 ATF_CHECK_MSG(state == PTHREAD_CANCEL_ENABLE,
1153 "state=%d PTHREAD_CANCEL_ENABLE=%d PTHREAD_CANCEL_DISABLE=%d",
1154 state, PTHREAD_CANCEL_ENABLE, PTHREAD_CANCEL_DISABLE);
1155
1156 ATF_CHECK_MSG(type == PTHREAD_CANCEL_DEFERRED,
1157 "type=%d"
1158 " PTHREAD_CANCEL_DEFERRED=%d PTHREAD_CANCEL_ASYNCHRONOUS=%d",
1159 type, PTHREAD_CANCEL_DEFERRED, PTHREAD_CANCEL_ASYNCHRONOUS);
1160
1161 return NULL;
1162 }
1163
1164 ATF_TC(defaults);
1165 ATF_TC_HEAD(defaults, tc)
1166 {
1167 atf_tc_set_md_var(tc, "descr", "Test default cancelability");
1168 }
1169 ATF_TC_BODY(defaults, tc)
1170 {
1171 pthread_t t;
1172
1173 fprintf(stderr, "initial thread\n");
1174 (void)defaults(NULL);
1175
1176 RZ(pthread_create(&t, NULL, &defaults, NULL));
1177
1178 alarm(1);
1179 RZ(pthread_join(t, NULL));
1180 }
1181
1182 static void *
1183 disable_enable(void *cookie)
1184 {
1185 int *n = cookie;
1186
1187 pthread_cleanup_push(&cleanup, &cleanup_done);
1188
1189 *n = 1;
1190 pthread_testcancel();
1191 *n = 2;
1192 RZ(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL));
1193 *n = 3;
1194 (void)pthread_barrier_wait(&bar);
1195 *n = 4;
1196 pthread_testcancel();
1197 *n = 5;
1198 (void)pthread_barrier_wait(&bar);
1199 *n = 6;
1200 pthread_testcancel();
1201 *n = 7;
1202 RZ(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL));
1203 *n = 8;
1204 pthread_testcancel(); /* cancel */
1205 *n = 9;
1206
1207 pthread_cleanup_pop(/*execute*/0);
1208 return NULL;
1209 }
1210
1211 ATF_TC(disable_enable);
1212 ATF_TC_HEAD(disable_enable, tc)
1213 {
1214 atf_tc_set_md_var(tc, "descr",
1215 "Test disabling and re-enabling cancellation");
1216 }
1217 ATF_TC_BODY(disable_enable, tc)
1218 {
1219 int n = 0;
1220 pthread_t t;
1221
1222 RZ(pthread_barrier_init(&bar, NULL, 2));
1223
1224 RZ(pthread_create(&t, NULL, &disable_enable, &n));
1225
1226 (void)pthread_barrier_wait(&bar);
1227 RZ(pthread_cancel(t));
1228 (void)pthread_barrier_wait(&bar);
1229
1230 alarm(1);
1231 RZ(pthread_join(t, NULL));
1232
1233 ATF_CHECK_MSG(n == 8, "n=%d", n);
1234 ATF_CHECK(cleanup_done);
1235 }
1236
1237 static void *
1238 notestcancel_loop_async(void *cookie)
1239 {
1240
1241 RZ(pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL));
1242
1243 pthread_cleanup_push(&cleanup, &cleanup_done);
1244 (void)pthread_barrier_wait(&bar);
1245 for (;;)
1246 __insn_barrier();
1247 pthread_cleanup_pop(/*execute*/0);
1248
1249 return NULL;
1250 }
1251
1252 ATF_TC(notestcancel_loop_async);
1253 ATF_TC_HEAD(notestcancel_loop_async, tc)
1254 {
1255 atf_tc_set_md_var(tc, "descr",
1256 "Test nothing in a loop with PTHREAD_CANCEL_ASYNCHRONOUS");
1257 }
1258 ATF_TC_BODY(notestcancel_loop_async, tc)
1259 {
1260 pthread_t t;
1261 void *result;
1262
1263 RZ(pthread_barrier_init(&bar, NULL, 2));
1264 RZ(pthread_create(&t, NULL, ¬estcancel_loop_async, NULL));
1265
1266 (void)pthread_barrier_wait(&bar);
1267 RZ(pthread_cancel(t));
1268
1269 atf_tc_expect_signal(SIGALRM, "lib/59135: PTHREAD_CANCEL_ASYNCHRONOUS"
1270 " doesn't do much");
1271 alarm(1);
1272 RZ(pthread_join(t, &result));
1273 ATF_CHECK_MSG(result == PTHREAD_CANCELED,
1274 "result=%p PTHREAD_CANCELED=%p", result, PTHREAD_CANCELED);
1275 ATF_CHECK(cleanup_done);
1276 }
1277
1278 static void *
1279 disable_enable_async(void *cookie)
1280 {
1281 int *n = cookie;
1282
1283 pthread_cleanup_push(&cleanup, &cleanup_done);
1284
1285 RZ(pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL));
1286
1287 *n = 1;
1288 pthread_testcancel();
1289 *n = 2;
1290 RZ(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL));
1291 *n = 3;
1292 (void)pthread_barrier_wait(&bar);
1293 *n = 4;
1294 pthread_testcancel();
1295 *n = 5;
1296 (void)pthread_barrier_wait(&bar);
1297 *n = 6;
1298 pthread_testcancel();
1299 *n = 7;
1300 RZ(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL)); /* cancel */
1301 *n = 8;
1302 pthread_testcancel();
1303 *n = 9;
1304
1305 pthread_cleanup_pop(/*execute*/0);
1306 return NULL;
1307 }
1308
1309 ATF_TC(disable_enable_async);
1310 ATF_TC_HEAD(disable_enable_async, tc)
1311 {
1312 atf_tc_set_md_var(tc, "descr",
1313 "Test disabling and re-enabling cancellation when asynchronous");
1314 }
1315 ATF_TC_BODY(disable_enable_async, tc)
1316 {
1317 int n = 0;
1318 pthread_t t;
1319
1320 RZ(pthread_barrier_init(&bar, NULL, 2));
1321
1322 RZ(pthread_create(&t, NULL, &disable_enable_async, &n));
1323
1324 (void)pthread_barrier_wait(&bar);
1325 RZ(pthread_cancel(t));
1326 (void)pthread_barrier_wait(&bar);
1327
1328 alarm(1);
1329 RZ(pthread_join(t, NULL));
1330
1331 ATF_CHECK_MSG(n == 7, "n=%d", n);
1332 ATF_CHECK(cleanup_done);
1333 }
1334
1335 static void *
1336 disable_enable_setcanceltype_async(void *cookie)
1337 {
1338 int *n = cookie;
1339
1340 pthread_cleanup_push(&cleanup, &cleanup_done);
1341
1342 *n = 1;
1343 pthread_testcancel();
1344 *n = 2;
1345 RZ(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL));
1346 *n = 3;
1347 (void)pthread_barrier_wait(&bar);
1348 *n = 4;
1349 pthread_testcancel();
1350 *n = 5;
1351 (void)pthread_barrier_wait(&bar);
1352 *n = 6;
1353 pthread_testcancel();
1354 *n = 7;
1355 RZ(pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL));
1356 *n = 8;
1357 pthread_testcancel();
1358 *n = 9;
1359 RZ(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL)); /* cancel */
1360 *n = 10;
1361 pthread_testcancel();
1362 *n = 11;
1363
1364 pthread_cleanup_pop(/*execute*/0);
1365 return NULL;
1366 }
1367
1368 ATF_TC(disable_enable_setcanceltype_async);
1369 ATF_TC_HEAD(disable_enable_setcanceltype_async, tc)
1370 {
1371 atf_tc_set_md_var(tc, "descr",
1372 "Test disabling cancellation, setting it async, and re-enabling");
1373 }
1374 ATF_TC_BODY(disable_enable_setcanceltype_async, tc)
1375 {
1376 int n = 0;
1377 pthread_t t;
1378
1379 RZ(pthread_barrier_init(&bar, NULL, 2));
1380
1381 RZ(pthread_create(&t, NULL, &disable_enable_setcanceltype_async, &n));
1382
1383 (void)pthread_barrier_wait(&bar);
1384 RZ(pthread_cancel(t));
1385 (void)pthread_barrier_wait(&bar);
1386
1387 alarm(1);
1388 RZ(pthread_join(t, NULL));
1389
1390 ATF_CHECK_MSG(n == 9, "n=%d", n);
1391 ATF_CHECK(cleanup_done);
1392 }
1393
1394 static void *
1395 setcanceltype_async(void *cookie)
1396 {
1397 int *n = cookie;
1398
1399 pthread_cleanup_push(&cleanup, &cleanup_done);
1400
1401 *n = 1;
1402 pthread_testcancel();
1403 *n = 2;
1404 (void)pthread_barrier_wait(&bar);
1405 *n = 3;
1406 (void)pthread_barrier_wait(&bar);
1407 *n = 4;
1408 RZ(pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,
1409 NULL)); /* cancel */
1410 *n = 5;
1411
1412 pthread_cleanup_pop(/*execute*/0);
1413 return NULL;
1414 }
1415
1416 ATF_TC(setcanceltype_async);
1417 ATF_TC_HEAD(setcanceltype_async, tc)
1418 {
1419 atf_tc_set_md_var(tc, "descr",
1420 "Test disabling cancellation, setting it async, and re-enabling");
1421 }
1422 ATF_TC_BODY(setcanceltype_async, tc)
1423 {
1424 int n = 0;
1425 pthread_t t;
1426
1427 RZ(pthread_barrier_init(&bar, NULL, 2));
1428
1429 RZ(pthread_create(&t, NULL, &setcanceltype_async, &n));
1430
1431 (void)pthread_barrier_wait(&bar);
1432 RZ(pthread_cancel(t));
1433 (void)pthread_barrier_wait(&bar);
1434
1435 alarm(1);
1436 RZ(pthread_join(t, NULL));
1437
1438 ATF_CHECK_MSG(n == 4, "n=%d", n);
1439 ATF_CHECK(cleanup_done);
1440 }
1441
1442 static void
1443 sighandler(int signo)
1444 {
1445 int state;
1446
1447 RZ(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &state));
1448 RZ(pthread_setcancelstate(state, NULL));
1449 }
1450
1451 static void *
1452 sigsafecancelstate(void *cookie)
1453 {
1454 atomic_ulong *n = cookie;
1455 char name[128];
1456
1457 pthread_cleanup_push(&cleanup, &cleanup_done);
1458 REQUIRE_LIBC(signal(SIGUSR1, &sighandler), SIG_ERR);
1459
1460 (void)pthread_barrier_wait(&bar);
1461
1462 while (atomic_load_explicit(n, memory_order_relaxed) != 0) {
1463 /*
1464 * Do some things that might take the same lock as
1465 * pthread_setcancelstate.
1466 */
1467 RZ(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL));
1468 RZ(pthread_getname_np(pthread_self(), name, sizeof(name)));
1469 RZ(pthread_setname_np(pthread_self(), "%s", name));
1470 }
1471
1472 pthread_cleanup_pop(/*execute*/1);
1473 return NULL;
1474 }
1475
1476 ATF_TC(sigsafecancelstate);
1477 ATF_TC_HEAD(sigsafecancelstate, tc)
1478 {
1479 atf_tc_set_md_var(tc, "descr",
1480 "Test pthread_setcancelstate async-signal-safety");
1481 }
1482 ATF_TC_BODY(sigsafecancelstate, tc)
1483 {
1484 pthread_t t;
1485 atomic_ulong n = 10000;
1486 void *result;
1487
1488 RZ(pthread_barrier_init(&bar, NULL, 2));
1489 RZ(pthread_create(&t, NULL, &sigsafecancelstate, &n));
1490
1491 (void)pthread_barrier_wait(&bar);
1492
1493 while (atomic_load_explicit(&n, memory_order_relaxed)) {
1494 pthread_kill(t, SIGUSR1);
1495 atomic_store_explicit(&n,
1496 atomic_load_explicit(&n, memory_order_relaxed) - 1,
1497 memory_order_relaxed);
1498 }
1499
1500 atf_tc_expect_signal(SIGALRM, "PR lib/59134: POSIX-1.2024:"
1501 " pthread_setcancelstate must be async-signal-safe");
1502 alarm(1);
1503 RZ(pthread_join(t, &result));
1504 ATF_CHECK_MSG(result == NULL, "result=%p", result);
1505 ATF_CHECK(cleanup_done);
1506 }
1507
1508 static void *
1509 testcancel_loop(void *cookie)
1510 {
1511
1512 pthread_cleanup_push(&cleanup, &cleanup_done);
1513 (void)pthread_barrier_wait(&bar);
1514 for (;;)
1515 pthread_testcancel();
1516 pthread_cleanup_pop(/*execute*/0);
1517
1518 return NULL;
1519 }
1520
1521 ATF_TC(testcancel_loop);
1522 ATF_TC_HEAD(testcancel_loop, tc)
1523 {
1524 atf_tc_set_md_var(tc, "descr",
1525 "Test pthread_testcancel in a loop");
1526 }
1527 ATF_TC_BODY(testcancel_loop, tc)
1528 {
1529 pthread_t t;
1530 void *result;
1531
1532 RZ(pthread_barrier_init(&bar, NULL, 2));
1533 RZ(pthread_create(&t, NULL, &testcancel_loop, NULL));
1534
1535 (void)pthread_barrier_wait(&bar);
1536 RZ(pthread_cancel(t));
1537
1538 alarm(1);
1539 RZ(pthread_join(t, &result));
1540 ATF_CHECK_MSG(result == PTHREAD_CANCELED,
1541 "result=%p PTHREAD_CANCELED=%p", result, PTHREAD_CANCELED);
1542 ATF_CHECK(cleanup_done);
1543 }
1544
1545 ATF_TP_ADD_TCS(tp)
1546 {
1547
1548 ADD_TEST_CANCELPOINT(cancelpoint_accept);
1549 ADD_TEST_CANCELPOINT(cancelpoint_accept4);
1550 ADD_TEST_CANCELPOINT(cancelpoint_aio_suspend);
1551 ADD_TEST_CANCELPOINT(cancelpoint_clock_nanosleep);
1552 ADD_TEST_CANCELPOINT(cancelpoint_close);
1553 ADD_TEST_CANCELPOINT(cancelpoint_cnd_timedwait);
1554 ADD_TEST_CANCELPOINT(cancelpoint_cnd_wait);
1555 ADD_TEST_CANCELPOINT(cancelpoint_connect);
1556 ADD_TEST_CANCELPOINT(cancelpoint_creat);
1557 ADD_TEST_CANCELPOINT(cancelpoint_fcntl_F_SETLKW);
1558 ADD_TEST_CANCELPOINT(cancelpoint_fcntl_F_OFD_SETLKW);
1559 ADD_TEST_CANCELPOINT(cancelpoint_fdatasync);
1560 ADD_TEST_CANCELPOINT(cancelpoint_fsync);
1561 ADD_TEST_CANCELPOINT(cancelpoint_lockf_F_LOCK);
1562 ADD_TEST_CANCELPOINT(cancelpoint_mq_receive);
1563 ADD_TEST_CANCELPOINT(cancelpoint_mq_send);
1564 ADD_TEST_CANCELPOINT(cancelpoint_mq_timedreceive);
1565 ADD_TEST_CANCELPOINT(cancelpoint_mq_timedsend);
1566 ADD_TEST_CANCELPOINT(cancelpoint_msgrcv);
1567 ADD_TEST_CANCELPOINT(cancelpoint_msgsnd);
1568 ADD_TEST_CANCELPOINT(cancelpoint_msync);
1569 ADD_TEST_CANCELPOINT(cancelpoint_nanosleep);
1570 ADD_TEST_CANCELPOINT(cancelpoint_open);
1571 ADD_TEST_CANCELPOINT(cancelpoint_openat);
1572 ADD_TEST_CANCELPOINT(cancelpoint_pause);
1573 ADD_TEST_CANCELPOINT(cancelpoint_poll);
1574 ADD_TEST_CANCELPOINT(cancelpoint_posix_close);
1575 ADD_TEST_CANCELPOINT(cancelpoint_ppoll);
1576 ADD_TEST_CANCELPOINT(cancelpoint_pread);
1577 ADD_TEST_CANCELPOINT(cancelpoint_pselect);
1578 ADD_TEST_CANCELPOINT(cancelpoint_pthread_cond_clockwait);
1579 ADD_TEST_CANCELPOINT(cancelpoint_pthread_cond_timedwait);
1580 ADD_TEST_CANCELPOINT(cancelpoint_pthread_cond_wait);
1581 ADD_TEST_CANCELPOINT(cancelpoint_pthread_join);
1582 ADD_TEST_CANCELPOINT(cancelpoint_pthread_testcancel);
1583 ADD_TEST_CANCELPOINT(cancelpoint_pwrite);
1584 ADD_TEST_CANCELPOINT(cancelpoint_read);
1585 ADD_TEST_CANCELPOINT(cancelpoint_readv);
1586 ADD_TEST_CANCELPOINT(cancelpoint_recv);
1587 ADD_TEST_CANCELPOINT(cancelpoint_recvfrom);
1588 ADD_TEST_CANCELPOINT(cancelpoint_recvmsg);
1589 ADD_TEST_CANCELPOINT(cancelpoint_select);
1590 ADD_TEST_CANCELPOINT(cancelpoint_send);
1591 ADD_TEST_CANCELPOINT(cancelpoint_sendto);
1592 ADD_TEST_CANCELPOINT(cancelpoint_sendmsg);
1593 ADD_TEST_CANCELPOINT(cancelpoint_sigsuspend);
1594 ADD_TEST_CANCELPOINT(cancelpoint_sigtimedwait);
1595 ADD_TEST_CANCELPOINT(cancelpoint_sigwait);
1596 ADD_TEST_CANCELPOINT(cancelpoint_sigwaitinfo);
1597 ADD_TEST_CANCELPOINT(cancelpoint_sleep);
1598 ADD_TEST_CANCELPOINT(cancelpoint_tcdrain);
1599 ADD_TEST_CANCELPOINT(cancelpoint_thrd_join);
1600 ADD_TEST_CANCELPOINT(cancelpoint_thrd_sleep);
1601 ADD_TEST_CANCELPOINT(cancelpoint_wait);
1602 ADD_TEST_CANCELPOINT(cancelpoint_waitid);
1603 ADD_TEST_CANCELPOINT(cancelpoint_waitpid);
1604 ADD_TEST_CANCELPOINT(cancelpoint_write);
1605 ADD_TEST_CANCELPOINT(cancelpoint_writev);
1606
1607 ATF_TP_ADD_TC(tp, cleanuppop0);
1608 ATF_TP_ADD_TC(tp, cleanuppop1);
1609 ATF_TP_ADD_TC(tp, cancelself_async);
1610 ATF_TP_ADD_TC(tp, cancelself_deferred);
1611 ATF_TP_ADD_TC(tp, defaults);
1612 ATF_TP_ADD_TC(tp, disable_enable);
1613 ATF_TP_ADD_TC(tp, disable_enable_async);
1614 ATF_TP_ADD_TC(tp, disable_enable_setcanceltype_async);
1615 ATF_TP_ADD_TC(tp, setcanceltype_async);
1616 ATF_TP_ADD_TC(tp, notestcancel_loop_async);
1617 ATF_TP_ADD_TC(tp, sigsafecancelstate);
1618 ATF_TP_ADD_TC(tp, testcancel_loop);
1619
1620 return atf_no_error();
1621 }
1622
1623