pthread_cancelstub.c revision 1.45.2.1 1 /* $NetBSD: pthread_cancelstub.c,v 1.45.2.1 2025/08/02 05:54:55 perseant Exp $ */
2
3 /*-
4 * Copyright (c) 2002, 2007 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Nathan J. Williams and Andrew Doran.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 /* Disable namespace mangling, Fortification is useless here anyway. */
33 #undef _FORTIFY_SOURCE
34
35 #include <sys/cdefs.h>
36 __RCSID("$NetBSD: pthread_cancelstub.c,v 1.45.2.1 2025/08/02 05:54:55 perseant Exp $");
37
38 /* Need to use libc-private names for atomic operations. */
39 #include "../../common/lib/libc/atomic/atomic_op_namespace.h"
40
41 #ifndef lint
42
43
44 /*
45 * This is necessary because the names are always weak (they are not
46 * POSIX functions).
47 */
48 #define fsync_range _fsync_range
49 #define pollts _pollts
50
51 /*
52 * XXX this is necessary to get the prototypes for the __sigsuspend14
53 * XXX and __msync13 internal names, instead of the application-visible
54 * XXX sigsuspend and msync names. It's kind of gross, but we're pretty
55 * XXX intimate with libc already.
56 */
57 #define __LIBC12_SOURCE__
58
59 #include <sys/msg.h>
60 #include <sys/types.h>
61 #include <sys/uio.h>
62 #include <sys/wait.h>
63 #include <aio.h>
64 #include <errno.h>
65 #include <fcntl.h>
66 #include <mqueue.h>
67 #include <poll.h>
68 #include <stdatomic.h>
69 #include <stdarg.h>
70 #include <termios.h>
71 #include <unistd.h>
72
73 #include <signal.h>
74 #include <sys/mman.h>
75 #include <sys/select.h>
76 #include <sys/socket.h>
77 #include <sys/event.h>
78 #include <sys/resource.h>
79
80 #include <compat/sys/mman.h>
81 #include <compat/sys/poll.h>
82 #include <compat/sys/select.h>
83 #include <compat/sys/event.h>
84 #include <compat/sys/wait.h>
85 #include <compat/sys/resource.h>
86 #include <compat/include/aio.h>
87 #include <compat/include/mqueue.h>
88 #include <compat/include/signal.h>
89 #include <compat/include/time.h>
90
91 #include "pthread.h"
92 #include "pthread_int.h"
93 #include "reentrant.h"
94
95 #define atomic_load_relaxed(p) \
96 atomic_load_explicit(p, memory_order_relaxed)
97
98 int pthread__cancel_stub_binder;
99
100 /*
101 * Provide declarations for the underlying libc syscall stubs. These
102 * _sys_* functions are symbols defined by libc which invoke the system
103 * call, without testing for cancellation. Below, we define non-_sys_*
104 * wrappers which surround calls to _sys_* by the equivalent of
105 * pthread_testcancel(). Both libc and libpthread define the
106 * non-_sys_* wrappers, but they are weak in libc and strong in
107 * libpthread, so programs linked against both will get the libpthread
108 * wrappers that test for cancellation.
109 */
110 __typeof(accept) _sys_accept;
111 __typeof(__aio_suspend50) _sys___aio_suspend50;
112 __typeof(clock_nanosleep) _sys_clock_nanosleep;
113 __typeof(close) _sys_close;
114 __typeof(connect) _sys_connect;
115 __typeof(fcntl) _sys_fcntl;
116 __typeof(fdatasync) _sys_fdatasync;
117 __typeof(fsync) _sys_fsync;
118 __typeof(fsync_range) _sys_fsync_range;
119 __typeof(__kevent100) _sys___kevent100;
120 __typeof(mq_receive) _sys_mq_receive;
121 __typeof(mq_send) _sys_mq_send;
122 __typeof(__mq_timedreceive50) _sys___mq_timedreceive50;
123 __typeof(__mq_timedsend50) _sys___mq_timedsend50;
124 __typeof(msgrcv) _sys_msgrcv;
125 __typeof(msgsnd) _sys_msgsnd;
126 __typeof(__msync13) _sys___msync13;
127 __typeof(__nanosleep50) _sys___nanosleep50;
128 __typeof(open) _sys_open;
129 __typeof(openat) _sys_openat;
130 __typeof(paccept) _sys_paccept;
131 __typeof(poll) _sys_poll;
132 __typeof(__pollts50) _sys___pollts50;
133 __typeof(pread) _sys_pread;
134 __typeof(__pselect50) _sys___pselect50;
135 __typeof(pwrite) _sys_pwrite;
136 __typeof(read) _sys_read;
137 __typeof(readv) _sys_readv;
138 __typeof(recvfrom) _sys_recvfrom;
139 __typeof(recvmmsg) _sys_recvmmsg;
140 __typeof(recvmsg) _sys_recvmsg;
141 __typeof(__select50) _sys___select50;
142 __typeof(sendmmsg) _sys_sendmmsg;
143 __typeof(sendmsg) _sys_sendmsg;
144 __typeof(sendto) _sys_sendto;
145 __typeof(__sigsuspend14) _sys___sigsuspend14;
146 __typeof(__wait450) _sys___wait450;
147 __typeof(write) _sys_write;
148 __typeof(writev) _sys_writev;
149
150 #define TESTCANCEL(id) do { \
151 if (__predict_true(!__uselibcstub) && \
152 __predict_false(atomic_load_relaxed(&(id)->pt_cancel) & \
153 PT_CANCEL_CANCELLED)) { \
154 membar_acquire(); \
155 pthread__cancelled(); \
156 } \
157 } while (0)
158
159
160 int
161 accept(int s, struct sockaddr *addr, socklen_t *addrlen)
162 {
163 int retval;
164 pthread_t self;
165
166 self = pthread__self();
167 TESTCANCEL(self);
168 retval = _sys_accept(s, addr, addrlen);
169 TESTCANCEL(self);
170
171 return retval;
172 }
173
174 int
175 accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
176 {
177 int retval;
178 pthread_t self;
179
180 self = pthread__self();
181 TESTCANCEL(self);
182 retval = _sys_paccept(s, addr, addrlen, NULL, flags);
183 TESTCANCEL(self);
184
185 return retval;
186 }
187
188 int
189 __aio_suspend50(const struct aiocb * const list[], int nent,
190 const struct timespec *timeout)
191 {
192 int retval;
193 pthread_t self;
194
195 self = pthread__self();
196 TESTCANCEL(self);
197 retval = _sys___aio_suspend50(list, nent, timeout);
198 TESTCANCEL(self);
199
200 return retval;
201 }
202
203 int
204 clock_nanosleep(clockid_t clock_id, int flags,
205 const struct timespec *rqtp, struct timespec *rmtp)
206 {
207 int retval;
208 pthread_t self;
209
210 self = pthread__self();
211 TESTCANCEL(self);
212 retval = _sys_clock_nanosleep(clock_id, flags, rqtp, rmtp);
213 TESTCANCEL(self);
214
215 return retval;
216 }
217
218 int
219 close(int d)
220 {
221 int retval;
222 pthread_t self;
223
224 self = pthread__self();
225 TESTCANCEL(self);
226 retval = _sys_close(d);
227 TESTCANCEL(self);
228
229 return retval;
230 }
231
232 int
233 connect(int s, const struct sockaddr *addr, socklen_t namelen)
234 {
235 int retval;
236 pthread_t self;
237
238 self = pthread__self();
239 TESTCANCEL(self);
240 retval = _sys_connect(s, addr, namelen);
241 TESTCANCEL(self);
242
243 return retval;
244 }
245
246 int
247 fcntl(int fd, int cmd, ...)
248 {
249 int retval;
250 pthread_t self;
251 va_list ap;
252
253 self = pthread__self();
254 TESTCANCEL(self);
255 va_start(ap, cmd);
256 retval = _sys_fcntl(fd, cmd, va_arg(ap, void *));
257 va_end(ap);
258 TESTCANCEL(self);
259
260 return retval;
261 }
262
263 int
264 fdatasync(int d)
265 {
266 int retval;
267 pthread_t self;
268
269 self = pthread__self();
270 TESTCANCEL(self);
271 retval = _sys_fdatasync(d);
272 TESTCANCEL(self);
273
274 return retval;
275 }
276
277 int
278 fsync(int d)
279 {
280 int retval;
281 pthread_t self;
282
283 self = pthread__self();
284 TESTCANCEL(self);
285 retval = _sys_fsync(d);
286 TESTCANCEL(self);
287
288 return retval;
289 }
290
291 int
292 fsync_range(int d, int f, off_t s, off_t e)
293 {
294 int retval;
295 pthread_t self;
296
297 self = pthread__self();
298 TESTCANCEL(self);
299 retval = _sys_fsync_range(d, f, s, e);
300 TESTCANCEL(self);
301
302 return retval;
303 }
304
305 int
306 __kevent100(int fd, const struct kevent *ev, size_t nev, struct kevent *rev,
307 size_t nrev, const struct timespec *ts)
308 {
309 int retval;
310 pthread_t self;
311
312 self = pthread__self();
313 TESTCANCEL(self);
314 retval = _sys___kevent100(fd, ev, nev, rev, nrev, ts);
315 TESTCANCEL(self);
316
317 return retval;
318 }
319
320 ssize_t
321 mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned *msg_prio)
322 {
323 ssize_t retval;
324 pthread_t self;
325
326 self = pthread__self();
327 TESTCANCEL(self);
328 retval = _sys_mq_receive(mqdes, msg_ptr, msg_len, msg_prio);
329 TESTCANCEL(self);
330
331 return retval;
332 }
333
334 int
335 mq_send(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned msg_prio)
336 {
337 int retval;
338 pthread_t self;
339
340 self = pthread__self();
341 TESTCANCEL(self);
342 retval = _sys_mq_send(mqdes, msg_ptr, msg_len, msg_prio);
343 TESTCANCEL(self);
344
345 return retval;
346 }
347
348 ssize_t
349 __mq_timedreceive50(mqd_t mqdes, char *msg_ptr, size_t msg_len,
350 unsigned *msg_prio, const struct timespec *abst)
351 {
352 ssize_t retval;
353 pthread_t self;
354
355 self = pthread__self();
356 TESTCANCEL(self);
357 retval = _sys___mq_timedreceive50(mqdes, msg_ptr, msg_len, msg_prio,
358 abst);
359 TESTCANCEL(self);
360
361 return retval;
362 }
363
364 int
365 __mq_timedsend50(mqd_t mqdes, const char *msg_ptr, size_t msg_len,
366 unsigned msg_prio, const struct timespec *abst)
367 {
368 int retval;
369 pthread_t self;
370
371 self = pthread__self();
372 TESTCANCEL(self);
373 retval = _sys___mq_timedsend50(mqdes, msg_ptr, msg_len, msg_prio,
374 abst);
375 TESTCANCEL(self);
376
377 return retval;
378 }
379
380 ssize_t
381 msgrcv(int msgid, void *msgp, size_t msgsz, long msgtyp, int msgflg)
382 {
383 ssize_t retval;
384 pthread_t self;
385
386 self = pthread__self();
387 TESTCANCEL(self);
388 retval = _sys_msgrcv(msgid, msgp, msgsz, msgtyp, msgflg);
389 TESTCANCEL(self);
390
391 return retval;
392 }
393
394 int
395 msgsnd(int msgid, const void *msgp, size_t msgsz, int msgflg)
396 {
397 int retval;
398 pthread_t self;
399
400 self = pthread__self();
401 TESTCANCEL(self);
402 retval = _sys_msgsnd(msgid, msgp, msgsz, msgflg);
403 TESTCANCEL(self);
404
405 return retval;
406 }
407
408 int
409 __msync13(void *addr, size_t len, int flags)
410 {
411 int retval;
412 pthread_t self;
413
414 self = pthread__self();
415 TESTCANCEL(self);
416 retval = _sys___msync13(addr, len, flags);
417 TESTCANCEL(self);
418
419 return retval;
420 }
421
422 int
423 __nanosleep50(const struct timespec *rqtp, struct timespec *rmtp)
424 {
425 int retval;
426 pthread_t self;
427
428 self = pthread__self();
429 TESTCANCEL(self);
430 /*
431 * For now, just nanosleep. In the future, maybe pass a ucontext_t
432 * to _lwp_nanosleep() and allow it to recycle our kernel stack.
433 */
434 retval = _sys___nanosleep50(rqtp, rmtp);
435 TESTCANCEL(self);
436
437 return retval;
438 }
439
440 int
441 open(const char *path, int flags, ...)
442 {
443 int retval;
444 pthread_t self;
445 va_list ap;
446
447 self = pthread__self();
448 TESTCANCEL(self);
449 va_start(ap, flags);
450 retval = _sys_open(path, flags, va_arg(ap, mode_t));
451 va_end(ap);
452 TESTCANCEL(self);
453
454 return retval;
455 }
456
457 int
458 openat(int fd, const char *path, int flags, ...)
459 {
460 int retval;
461 pthread_t self;
462 va_list ap;
463
464 self = pthread__self();
465 TESTCANCEL(self);
466 va_start(ap, flags);
467 retval = _sys_openat(fd, path, flags, va_arg(ap, mode_t));
468 va_end(ap);
469 TESTCANCEL(self);
470
471 return retval;
472 }
473
474 int
475 poll(struct pollfd *fds, nfds_t nfds, int timeout)
476 {
477 int retval;
478 pthread_t self;
479
480 self = pthread__self();
481 TESTCANCEL(self);
482 retval = _sys_poll(fds, nfds, timeout);
483 TESTCANCEL(self);
484
485 return retval;
486 }
487
488 int
489 __pollts50(struct pollfd *fds, nfds_t nfds, const struct timespec *ts,
490 const sigset_t *sigmask)
491 {
492 int retval;
493 pthread_t self;
494
495 self = pthread__self();
496 TESTCANCEL(self);
497 retval = _sys___pollts50(fds, nfds, ts, sigmask);
498 TESTCANCEL(self);
499
500 return retval;
501 }
502
503 ssize_t
504 pread(int d, void *buf, size_t nbytes, off_t offset)
505 {
506 ssize_t retval;
507 pthread_t self;
508
509 self = pthread__self();
510 TESTCANCEL(self);
511 retval = _sys_pread(d, buf, nbytes, offset);
512 TESTCANCEL(self);
513
514 return retval;
515 }
516
517 int
518 __pselect50(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
519 const struct timespec *timeout, const sigset_t *sigmask)
520 {
521 int retval;
522 pthread_t self;
523
524 self = pthread__self();
525 TESTCANCEL(self);
526 retval = _sys___pselect50(nfds, readfds, writefds, exceptfds, timeout,
527 sigmask);
528 TESTCANCEL(self);
529
530 return retval;
531 }
532
533 ssize_t
534 pwrite(int d, const void *buf, size_t nbytes, off_t offset)
535 {
536 ssize_t retval;
537 pthread_t self;
538
539 self = pthread__self();
540 TESTCANCEL(self);
541 retval = _sys_pwrite(d, buf, nbytes, offset);
542 TESTCANCEL(self);
543
544 return retval;
545 }
546
547 ssize_t
548 read(int d, void *buf, size_t nbytes)
549 {
550 ssize_t retval;
551 pthread_t self;
552
553 self = pthread__self();
554 TESTCANCEL(self);
555 retval = _sys_read(d, buf, nbytes);
556 TESTCANCEL(self);
557
558 return retval;
559 }
560
561 ssize_t
562 readv(int d, const struct iovec *iov, int iovcnt)
563 {
564 ssize_t retval;
565 pthread_t self;
566
567 self = pthread__self();
568 TESTCANCEL(self);
569 retval = _sys_readv(d, iov, iovcnt);
570 TESTCANCEL(self);
571
572 return retval;
573 }
574
575 ssize_t
576 recvfrom(int s, void * restrict buf, size_t len, int flags,
577 struct sockaddr * restrict from, socklen_t * restrict fromlen)
578 {
579 ssize_t retval;
580 pthread_t self;
581
582 self = pthread__self();
583 TESTCANCEL(self);
584 retval = _sys_recvfrom(s, buf, len, flags, from, fromlen);
585 TESTCANCEL(self);
586
587 return retval;
588 }
589
590 int
591 recvmmsg(int s, struct mmsghdr *mmsg, unsigned int vlen,
592 unsigned int flags, struct timespec *timeout)
593 {
594 ssize_t retval;
595 pthread_t self;
596
597 self = pthread__self();
598 TESTCANCEL(self);
599 retval = _sys_recvmmsg(s, mmsg, vlen, flags, timeout);
600 TESTCANCEL(self);
601
602 return retval;
603 }
604
605 ssize_t
606 recvmsg(int s, struct msghdr *msg, int flags)
607 {
608 ssize_t retval;
609 pthread_t self;
610
611 self = pthread__self();
612 TESTCANCEL(self);
613 retval = _sys_recvmsg(s, msg, flags);
614 TESTCANCEL(self);
615
616 return retval;
617 }
618
619 int
620 __select50(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
621 struct timeval *timeout)
622 {
623 int retval;
624 pthread_t self;
625
626 self = pthread__self();
627 TESTCANCEL(self);
628 retval = _sys___select50(nfds, readfds, writefds, exceptfds, timeout);
629 TESTCANCEL(self);
630
631 return retval;
632 }
633
634 int
635 sendmmsg(int s, struct mmsghdr *mmsg, unsigned int vlen,
636 unsigned int flags)
637 {
638 int retval;
639 pthread_t self;
640
641 self = pthread__self();
642 TESTCANCEL(self);
643 retval = _sys_sendmmsg(s, mmsg, vlen, flags);
644 TESTCANCEL(self);
645
646 return retval;
647 }
648
649 ssize_t
650 sendmsg(int s, const struct msghdr *msg, int flags)
651 {
652 int retval;
653 pthread_t self;
654
655 self = pthread__self();
656 TESTCANCEL(self);
657 retval = _sys_sendmsg(s, msg, flags);
658 TESTCANCEL(self);
659
660 return retval;
661 }
662
663 ssize_t
664 sendto(int s, const void *msg, size_t len, int flags,
665 const struct sockaddr *to, socklen_t tolen)
666 {
667 int retval;
668 pthread_t self;
669
670 self = pthread__self();
671 TESTCANCEL(self);
672 retval = _sys_sendto(s, msg, len, flags, to, tolen);
673 TESTCANCEL(self);
674
675 return retval;
676 }
677
678 int
679 __sigsuspend14(const sigset_t *sigmask)
680 {
681 pthread_t self;
682 int retval;
683
684 self = pthread__self();
685 TESTCANCEL(self);
686 retval = _sys___sigsuspend14(sigmask);
687 TESTCANCEL(self);
688
689 return retval;
690 }
691
692 int
693 __sigtimedwait50(const sigset_t * restrict set, siginfo_t * restrict info,
694 const struct timespec * restrict timeout)
695 {
696 pthread_t self;
697 int retval;
698 struct timespec tout, *tp;
699
700 if (timeout) {
701 tout = *timeout;
702 tp = &tout;
703 } else
704 tp = NULL;
705
706 self = pthread__self();
707 TESTCANCEL(self);
708 retval = ____sigtimedwait50(set, info, tp);
709 TESTCANCEL(self);
710
711 return retval;
712 }
713
714 int
715 sigwait(const sigset_t * restrict set, int * restrict sig)
716 {
717 pthread_t self;
718 int saved_errno;
719 int new_errno;
720 int retval;
721
722 self = pthread__self();
723 saved_errno = errno;
724 TESTCANCEL(self);
725 retval = ____sigtimedwait50(set, NULL, NULL);
726 TESTCANCEL(self);
727 new_errno = errno;
728 errno = saved_errno;
729 if (retval < 0) {
730 return new_errno;
731 }
732 *sig = retval;
733 return 0;
734 }
735
736 int
737 tcdrain(int fd)
738 {
739 int retval;
740 pthread_t self;
741
742 self = pthread__self();
743 TESTCANCEL(self);
744 retval = ioctl(fd, TIOCDRAIN, 0);
745 TESTCANCEL(self);
746
747 return retval;
748 }
749
750 pid_t
751 __wait450(pid_t wpid, int *status, int options, struct rusage *rusage)
752 {
753 pid_t retval;
754 pthread_t self;
755
756 self = pthread__self();
757 TESTCANCEL(self);
758 retval = _sys___wait450(wpid, status, options, rusage);
759 TESTCANCEL(self);
760
761 return retval;
762 }
763
764 ssize_t
765 write(int d, const void *buf, size_t nbytes)
766 {
767 ssize_t retval;
768 pthread_t self;
769
770 self = pthread__self();
771 TESTCANCEL(self);
772 retval = _sys_write(d, buf, nbytes);
773 TESTCANCEL(self);
774
775 return retval;
776 }
777
778 ssize_t
779 writev(int d, const struct iovec *iov, int iovcnt)
780 {
781 ssize_t retval;
782 pthread_t self;
783
784 self = pthread__self();
785 TESTCANCEL(self);
786 retval = _sys_writev(d, iov, iovcnt);
787 TESTCANCEL(self);
788
789 return retval;
790 }
791
792 __strong_alias(_clock_nanosleep, clock_nanosleep)
793 __strong_alias(_close, close)
794 __strong_alias(_fcntl, fcntl)
795 __strong_alias(_fdatasync, fdatasync)
796 __strong_alias(_fsync, fsync)
797 __weak_alias(fsync_range, _fsync_range)
798 __strong_alias(_mq_receive, mq_receive)
799 __strong_alias(_mq_send, mq_send)
800 __strong_alias(_msgrcv, msgrcv)
801 __strong_alias(_msgsnd, msgsnd)
802 __strong_alias(___msync13, __msync13)
803 __strong_alias(___nanosleep50, __nanosleep50)
804 __strong_alias(_open, open)
805 __strong_alias(_openat, openat)
806 __strong_alias(_poll, poll)
807 __strong_alias(_pread, pread)
808 __strong_alias(_pwrite, pwrite)
809 __strong_alias(_read, read)
810 __strong_alias(_readv, readv)
811 __strong_alias(_recvfrom, recvfrom)
812 __strong_alias(_recvmmsg, recvmmsg)
813 __strong_alias(_recvmsg, recvmsg)
814 __strong_alias(_sendmmsg, sendmmsg)
815 __strong_alias(_sendmsg, sendmsg)
816 __strong_alias(_sendto, sendto)
817 __strong_alias(_sigwait, sigwait)
818 __strong_alias(_write, write)
819 __strong_alias(_writev, writev)
820
821 #endif /* !lint */
822