diff options
| author | ShengYi Hung <aokblast@FreeBSD.org> | 2026-11-05 00:03:01 +0000 |
|---|---|---|
| committer | ShengYi Hung <aokblast@FreeBSD.org> | 2026-11-05 16:01:55 +0000 |
| commit | 2734bbbcba3cd6ff2bf4382fb6e85b884beb966e (patch) | |
| tree | 9be632c3180758b08c908da5b0cdb612deb03c3a | |
| parent | 71937d8e11a6b7fdb3c1b308d5f7c8b30dac5ca7 (diff) | |
libthr: Create landing pad in thr_once in C++ exception
In _thr_once, if init_routine fails with exception, the stack allocate
__cup will become invalid when unwinder walk back and free the stack of
thr_once. This cause cleanup linked list be dangling. In here, we give
the cleanup function a landing pad so that we td can correctly point
to previous cleanup function.
Reviewed by: kib
MFC after: 2 weeks
Differential Revision: https://reviews.freebsd.org/D61212
| -rw-r--r-- | lib/libthr/thread/thr_private.h | 16 |
1 files changed, 15 insertions, 1 deletions
diff --git a/lib/libthr/thread/thr_private.h b/lib/libthr/thread/thr_private.h index 3cc0fe61de00..9ea56b5b8a35 100644 --- a/lib/libthr/thread/thr_private.h +++ b/lib/libthr/thread/thr_private.h @@ -249,7 +249,9 @@ struct pthread_cleanup { }; #define THR_CLEANUP_PUSH(td, func, arg) { \ - struct pthread_cleanup __cup; \ + struct pthread_cleanup __cup \ + __attribute__((__cleanup__( \ + _thr_cleanup_unwind))); \ \ __cup.routine = func; \ __cup.routine_arg = arg; \ @@ -949,6 +951,18 @@ _thr_check_init(void) _libpthread_init(NULL); } +static inline void +_thr_cleanup_unwind(struct pthread_cleanup *cup) +{ + struct pthread *curthread; + + curthread = _get_curthread(); + if (curthread->cleanup == cup) { + curthread->cleanup = cup->prev; + cup->routine(cup->routine_arg); + } +} + struct wake_addr *_thr_alloc_wake_addr(void); void _thr_release_wake_addr(struct wake_addr *); int _thr_sleep(struct pthread *, int, const struct timespec *); |
