Home | History | Annotate | Line # | Download | only in libpthread
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, &notestcancel_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