Home | History | Annotate | Line # | Download | only in libpthread
t_compat_cancel.c revision 1.2
      1 /*	$NetBSD: t_compat_cancel.c,v 1.2 2025/04/11 02:07:17 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 #define	__LIBC12_SOURCE__	/* expose compat declarations */
     30 
     31 #include <sys/cdefs.h>
     32 __RCSID("$NetBSD: t_compat_cancel.c,v 1.2 2025/04/11 02:07:17 riastradh Exp $");
     33 
     34 #include <sys/event.h>
     35 #include <sys/mman.h>
     36 
     37 #include <aio.h>
     38 #include <atf-c.h>
     39 #include <mqueue.h>
     40 #include <pthread.h>
     41 #include <signal.h>
     42 
     43 #include <compat/sys/event.h>
     44 #include <compat/sys/mman.h>
     45 #include <compat/sys/poll.h>
     46 #include <compat/sys/select.h>
     47 
     48 #include <compat/include/aio.h>
     49 #include <compat/include/mqueue.h>
     50 #include <compat/include/signal.h>
     51 #include <compat/include/time.h>
     52 
     53 #include "cancelpoint.h"
     54 #include "h_macros.h"
     55 
     56 pthread_barrier_t bar;
     57 bool cleanup_done;
     58 
     59 static void
     60 cancelpoint_compat100_kevent(void)
     61 {
     62 	int kq;
     63 	struct kevent100 ev;
     64 
     65 	memset(&ev, 0, sizeof(ev));
     66 	ev.ident = SIGUSR1;
     67 	ev.filter = EVFILT_SIGNAL;
     68 	ev.flags = EV_ADD|EV_ENABLE;
     69 	ev.fflags = 0;
     70 	ev.data = 0;
     71 	ev.udata = 0;
     72 
     73 	RL(kq = kqueue());
     74 	RL(__kevent50(kq, &ev, 1, NULL, 1, &(const struct timespec){0,0}));
     75 	cancelpointready();
     76 	RL(__kevent50(kq, NULL, 0, &ev, 1, NULL));
     77 }
     78 
     79 static void
     80 cancelpoint_compat12_msync(void)
     81 {
     82 	const unsigned long pagesize = sysconf(_SC_PAGESIZE);
     83 	int fd;
     84 	void *map;
     85 
     86 	RL(fd = open("file", O_RDWR|O_CREAT, 0666));
     87 	RL(ftruncate(fd, pagesize));
     88 	REQUIRE_LIBC(map = mmap(NULL, pagesize, PROT_READ|PROT_WRITE,
     89 		MAP_SHARED, fd, 0),
     90 	    MAP_FAILED);
     91 	cancelpointready();
     92 	RL(msync(map, pagesize));
     93 }
     94 
     95 static void
     96 cancelpoint_compat50___sigtimedwait(void)
     97 {
     98 	sigset_t mask, omask;
     99 	siginfo_t info;
    100 	struct timespec50 t = {.tv_sec = 2, .tv_nsec = 0};
    101 
    102 	RL(__sigfillset14(&mask));
    103 	RL(__sigprocmask14(SIG_BLOCK, &mask, &omask));
    104 	cancelpointready();
    105 	RL(__sigtimedwait(&omask, &info, &t));
    106 }
    107 
    108 static void
    109 cancelpoint_compat50_aio_suspend(void)
    110 {
    111 	int fd[2];
    112 	char buf[32];
    113 	struct aiocb aio = {
    114 		.aio_offset = 0,
    115 		.aio_buf = buf,
    116 		.aio_nbytes = sizeof(buf),
    117 		.aio_fildes = -1,
    118 	};
    119 	const struct aiocb *const aiolist[] = { &aio };
    120 
    121 	RL(pipe(fd));
    122 	aio.aio_fildes = fd[0];
    123 	RL(aio_read(&aio));
    124 	cancelpointready();
    125 	RL(aio_suspend(aiolist, __arraycount(aiolist), NULL));
    126 }
    127 
    128 static void
    129 cancelpoint_compat50_kevent(void)
    130 {
    131 	int kq;
    132 	struct kevent100 ev;
    133 
    134 	memset(&ev, 0, sizeof(ev));
    135 	ev.ident = SIGUSR1;
    136 	ev.filter = EVFILT_SIGNAL;
    137 	ev.flags = EV_ADD|EV_ENABLE;
    138 	ev.fflags = 0;
    139 	ev.data = 0;
    140 	ev.udata = 0;
    141 
    142 	RL(kq = kqueue());
    143 	RL(kevent(kq, &ev, 1, NULL, 1, &(const struct timespec50){0,0}));
    144 	cancelpointready();
    145 	RL(kevent(kq, NULL, 0, &ev, 1, NULL));
    146 }
    147 
    148 static void
    149 cancelpoint_compat50_mq_timedreceive(void)
    150 {
    151 	mqd_t mq;
    152 	char buf[32];
    153 	struct timespec50 t = {.tv_sec = 2, .tv_nsec = 0};
    154 
    155 	RL(mq = mq_open("mq", O_RDWR|O_CREAT, 0666, NULL));
    156 	cancelpointready();
    157 	RL(mq_timedreceive(mq, buf, sizeof(buf), NULL, &t));
    158 }
    159 
    160 static void
    161 cancelpoint_compat50_mq_timedsend(void)
    162 {
    163 	mqd_t mq;
    164 	char buf[32] = {0};
    165 	struct timespec50 t = {.tv_sec = 2, .tv_nsec = 0};
    166 
    167 	RL(mq = mq_open("mq", O_RDWR|O_CREAT, 0666, NULL));
    168 	cancelpointready();
    169 	RL(mq_timedsend(mq, buf, sizeof(buf), 0, &t));
    170 }
    171 
    172 static void
    173 cancelpoint_compat50_nanosleep(void)
    174 {
    175 	struct timespec50 t = {.tv_sec = 2, .tv_nsec = 0};
    176 
    177 	cancelpointready();
    178 	RL(nanosleep(&t, NULL));
    179 }
    180 
    181 static void
    182 cancelpoint_compat50_pollts(void)
    183 {
    184 	int fd[2];
    185 	struct pollfd pfd;
    186 	struct timespec50 t = {.tv_sec = 2, .tv_nsec = 0};
    187 
    188 	RL(pipe(fd));
    189 	pfd.fd = fd[0];
    190 	pfd.events = POLLIN;
    191 	cancelpointready();
    192 	RL(pollts(&pfd, 1, &t, NULL));
    193 }
    194 
    195 static void
    196 cancelpoint_compat50_pselect(void)
    197 {
    198 	int fd[2];
    199 	fd_set readfd;
    200 	struct timespec50 t = {.tv_sec = 2, .tv_nsec = 0};
    201 
    202 	FD_ZERO(&readfd);
    203 
    204 	RL(pipe(fd));
    205 	FD_SET(fd[0], &readfd);
    206 	cancelpointready();
    207 	RL(pselect(fd[0] + 1, &readfd, NULL, NULL, &t, NULL));
    208 }
    209 
    210 static void
    211 cancelpoint_compat50_select(void)
    212 {
    213 	int fd[2];
    214 	fd_set readfd;
    215 	struct timeval50 t = {.tv_sec = 1, .tv_usec = 0};
    216 
    217 	FD_ZERO(&readfd);
    218 
    219 	RL(pipe(fd));
    220 	FD_SET(fd[0], &readfd);
    221 	cancelpointready();
    222 	RL(select(fd[0] + 1, &readfd, NULL, NULL, &t));
    223 }
    224 
    225 static void
    226 cancelpoint_compat13_sigsuspend(void)
    227 {
    228 	sigset13_t mask, omask;
    229 
    230 	RL(sigfillset(&mask));
    231 	RL(sigprocmask(SIG_BLOCK, &mask, &omask));
    232 	cancelpointready();
    233 	RL(sigsuspend(&omask));
    234 }
    235 
    236 static void
    237 cancelpoint_compat50_sigtimedwait(void)
    238 {
    239 	sigset_t mask, omask;
    240 	siginfo_t info;
    241 	struct timespec50 t = {.tv_sec = 2, .tv_nsec = 0};
    242 
    243 	RL(__sigfillset14(&mask));
    244 	RL(__sigprocmask14(SIG_BLOCK, &mask, &omask));
    245 	cancelpointready();
    246 	RL(sigtimedwait(&omask, &info, &t));
    247 }
    248 
    249 TEST_CANCELPOINT(cancelpoint_compat100_kevent, __nothing)
    250 TEST_CANCELPOINT(cancelpoint_compat12_msync, __nothing)
    251 TEST_CANCELPOINT(cancelpoint_compat13_sigsuspend,
    252     atf_tc_expect_signal(SIGALRM, "PR lib/59240: POSIX.1-2024:"
    253 	" cancellation point audit"))
    254 TEST_CANCELPOINT(cancelpoint_compat50___sigtimedwait,
    255     atf_tc_expect_signal(SIGALRM, "PR lib/59240: POSIX.1-2024:"
    256 	" cancellation point audit"))
    257 TEST_CANCELPOINT(cancelpoint_compat50_aio_suspend, __nothing)
    258 TEST_CANCELPOINT(cancelpoint_compat50_kevent, __nothing)
    259 TEST_CANCELPOINT(cancelpoint_compat50_mq_timedreceive, __nothing)
    260 TEST_CANCELPOINT(cancelpoint_compat50_mq_timedsend, __nothing)
    261 TEST_CANCELPOINT(cancelpoint_compat50_nanosleep, __nothing)
    262 TEST_CANCELPOINT(cancelpoint_compat50_pollts, __nothing)
    263 TEST_CANCELPOINT(cancelpoint_compat50_pselect, __nothing)
    264 TEST_CANCELPOINT(cancelpoint_compat50_select, __nothing)
    265 TEST_CANCELPOINT(cancelpoint_compat50_sigtimedwait,
    266     atf_tc_expect_signal(SIGALRM, "PR lib/59240: POSIX.1-2024:"
    267 	" cancellation point audit"))
    268 
    269 ATF_TP_ADD_TCS(tp)
    270 {
    271 
    272 	ADD_TEST_CANCELPOINT(cancelpoint_compat100_kevent);
    273 	ADD_TEST_CANCELPOINT(cancelpoint_compat12_msync);
    274 	ADD_TEST_CANCELPOINT(cancelpoint_compat13_sigsuspend);
    275 	ADD_TEST_CANCELPOINT(cancelpoint_compat50___sigtimedwait);
    276 	ADD_TEST_CANCELPOINT(cancelpoint_compat50_aio_suspend);
    277 	ADD_TEST_CANCELPOINT(cancelpoint_compat50_kevent);
    278 	ADD_TEST_CANCELPOINT(cancelpoint_compat50_mq_timedreceive);
    279 	ADD_TEST_CANCELPOINT(cancelpoint_compat50_mq_timedsend);
    280 	ADD_TEST_CANCELPOINT(cancelpoint_compat50_nanosleep);
    281 	ADD_TEST_CANCELPOINT(cancelpoint_compat50_pollts);
    282 	ADD_TEST_CANCELPOINT(cancelpoint_compat50_pselect);
    283 	ADD_TEST_CANCELPOINT(cancelpoint_compat50_select);
    284 	ADD_TEST_CANCELPOINT(cancelpoint_compat50_sigtimedwait);
    285 
    286 	return atf_no_error();
    287 }
    288