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