thr_sig.c (211737) | thr_sig.c (212076) |
---|---|
1/* 2 * Copyright (c) 2005, David Xu <davidxu@freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 9 unchanged lines hidden (view full) --- 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * | 1/* 2 * Copyright (c) 2005, David Xu <davidxu@freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 9 unchanged lines hidden (view full) --- 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * |
26 * $FreeBSD: head/lib/libthr/thread/thr_sig.c 211737 2010-08-24 09:57:06Z davidxu $ | 26 * $FreeBSD: head/lib/libthr/thread/thr_sig.c 212076 2010-09-01 02:18:33Z davidxu $ |
27 */ 28 29#include "namespace.h" 30#include <sys/param.h> 31#include <sys/types.h> 32#include <sys/signalvar.h> 33#include <signal.h> 34#include <errno.h> | 27 */ 28 29#include "namespace.h" 30#include <sys/param.h> 31#include <sys/types.h> 32#include <sys/signalvar.h> 33#include <signal.h> 34#include <errno.h> |
35#include <fcntl.h> 36#include <unistd.h> | |
37#include <string.h> 38#include <pthread.h> 39#include "un-namespace.h" | 35#include <string.h> 36#include <pthread.h> 37#include "un-namespace.h" |
38#include "libc_private.h" |
|
40 41#include "thr_private.h" 42 43/* #define DEBUG_SIGNAL */ 44#ifdef DEBUG_SIGNAL 45#define DBG_MSG stdout_debug 46#else 47#define DBG_MSG(x...) 48#endif 49 | 39 40#include "thr_private.h" 41 42/* #define DEBUG_SIGNAL */ 43#ifdef DEBUG_SIGNAL 44#define DBG_MSG stdout_debug 45#else 46#define DBG_MSG(x...) 47#endif 48 |
50extern int __pause(void); | 49struct usigaction { 50 struct sigaction sigact; 51 struct urwlock lock; 52}; 53 54static struct usigaction _thr_sigact[_SIG_MAXSIG]; 55 56static void thr_sighandler(int, siginfo_t *, void *); 57static void handle_signal(struct sigaction *, int, siginfo_t *, ucontext_t *); 58static void check_deferred_signal(struct pthread *); 59static void check_suspend(struct pthread *); 60static void check_cancel(struct pthread *curthread, ucontext_t *ucp); 61 |
51int ___pause(void); 52int _raise(int); 53int __sigtimedwait(const sigset_t *set, siginfo_t *info, 54 const struct timespec * timeout); 55int _sigtimedwait(const sigset_t *set, siginfo_t *info, 56 const struct timespec * timeout); 57int __sigwaitinfo(const sigset_t *set, siginfo_t *info); 58int _sigwaitinfo(const sigset_t *set, siginfo_t *info); 59int __sigwait(const sigset_t *set, int *sig); 60int _sigwait(const sigset_t *set, int *sig); 61int __sigsuspend(const sigset_t *sigmask); | 62int ___pause(void); 63int _raise(int); 64int __sigtimedwait(const sigset_t *set, siginfo_t *info, 65 const struct timespec * timeout); 66int _sigtimedwait(const sigset_t *set, siginfo_t *info, 67 const struct timespec * timeout); 68int __sigwaitinfo(const sigset_t *set, siginfo_t *info); 69int _sigwaitinfo(const sigset_t *set, siginfo_t *info); 70int __sigwait(const sigset_t *set, int *sig); 71int _sigwait(const sigset_t *set, int *sig); 72int __sigsuspend(const sigset_t *sigmask); |
73int _sigaction(int, const struct sigaction *, struct sigaction *); |
|
62int _setcontext(const ucontext_t *); 63int _swapcontext(ucontext_t *, const ucontext_t *); 64 | 74int _setcontext(const ucontext_t *); 75int _swapcontext(ucontext_t *, const ucontext_t *); 76 |
65static void | 77static const sigset_t _thr_deferset={{ 78 0xffffffff & ~(_SIG_BIT(SIGBUS)|_SIG_BIT(SIGILL)|_SIG_BIT(SIGFPE)| 79 _SIG_BIT(SIGSEGV)|_SIG_BIT(SIGTRAP)|_SIG_BIT(SIGSYS)), 80 0xffffffff, 81 0xffffffff, 82 0xffffffff}}; 83 84static const sigset_t _thr_maskset={{ 85 0xffffffff, 86 0xffffffff, 87 0xffffffff, 88 0xffffffff}}; 89 90void 91_thr_signal_block(struct pthread *curthread) 92{ 93 94 if (curthread->sigblock > 0) { 95 curthread->sigblock++; 96 return; 97 } 98 __sys_sigprocmask(SIG_BLOCK, &_thr_maskset, &curthread->sigmask); 99 curthread->sigblock++; 100} 101 102void 103_thr_signal_unblock(struct pthread *curthread) 104{ 105 if (--curthread->sigblock == 0) 106 __sys_sigprocmask(SIG_SETMASK, &curthread->sigmask, NULL); 107} 108 109int 110_thr_send_sig(struct pthread *thread, int sig) 111{ 112 return thr_kill(thread->tid, sig); 113} 114 115static inline void |
66remove_thr_signals(sigset_t *set) 67{ 68 if (SIGISMEMBER(*set, SIGCANCEL)) 69 SIGDELSET(*set, SIGCANCEL); 70} 71 72static const sigset_t * 73thr_remove_thr_signals(const sigset_t *set, sigset_t *newset) 74{ | 116remove_thr_signals(sigset_t *set) 117{ 118 if (SIGISMEMBER(*set, SIGCANCEL)) 119 SIGDELSET(*set, SIGCANCEL); 120} 121 122static const sigset_t * 123thr_remove_thr_signals(const sigset_t *set, sigset_t *newset) 124{ |
75 const sigset_t *pset; 76 77 if (SIGISMEMBER(*set, SIGCANCEL)) { 78 *newset = *set; 79 SIGDELSET(*newset, SIGCANCEL); 80 pset = newset; 81 } else 82 pset = set; 83 return (pset); | 125 *newset = *set; 126 remove_thr_signals(newset); 127 return (newset); |
84} 85 86static void 87sigcancel_handler(int sig __unused, | 128} 129 130static void 131sigcancel_handler(int sig __unused, |
88 siginfo_t *info __unused, ucontext_t *ucp __unused) | 132 siginfo_t *info __unused, ucontext_t *ucp) |
89{ 90 struct pthread *curthread = _get_curthread(); | 133{ 134 struct pthread *curthread = _get_curthread(); |
135 int err; |
|
91 | 136 |
92 curthread->in_sigcancel_handler++; 93 _thr_ast(curthread); 94 curthread->in_sigcancel_handler--; | 137 if (THR_IN_CRITICAL(curthread)) 138 return; 139 err = errno; 140 check_suspend(curthread); 141 check_cancel(curthread, ucp); 142 errno = err; |
95} 96 | 143} 144 |
145typedef void (*ohandler)(int sig, int code, 146 struct sigcontext *scp, char *addr, __sighandler_t *catcher); 147 148/* 149 * The signal handler wrapper is entered with all signal masked. 150 */ 151static void 152thr_sighandler(int sig, siginfo_t *info, void *_ucp) 153{ 154 struct pthread *curthread = _get_curthread(); 155 ucontext_t *ucp = _ucp; 156 struct sigaction act; 157 int err; 158 159 err = errno; 160 _thr_rwl_rdlock(&_thr_sigact[sig-1].lock); 161 act = _thr_sigact[sig-1].sigact; 162 _thr_rwl_unlock(&_thr_sigact[sig-1].lock); 163 errno = err; 164 165 /* 166 * if a thread is in critical region, for example it holds low level locks, 167 * try to defer the signal processing, however if the signal is synchronous 168 * signal, it means a bad thing has happened, this is a programming error, 169 * resuming fault point can not help anything (normally causes deadloop), 170 * so here we let user code handle it immediately. 171 */ 172 if (THR_IN_CRITICAL(curthread) && SIGISMEMBER(_thr_deferset, sig)) { 173 memcpy(&curthread->deferred_sigact, &act, sizeof(struct sigaction)); 174 memcpy(&curthread->deferred_siginfo, info, sizeof(siginfo_t)); 175 curthread->deferred_sigmask = ucp->uc_sigmask; 176 /* mask all signals, we will restore it later. */ 177 ucp->uc_sigmask = _thr_deferset; 178 return; 179 } 180 181 handle_signal(&act, sig, info, ucp); 182} 183 184static void 185handle_signal(struct sigaction *actp, int sig, siginfo_t *info, ucontext_t *ucp) 186{ 187 struct pthread *curthread = _get_curthread(); 188 ucontext_t uc2; 189 __siginfohandler_t *sigfunc; 190 int cancel_defer; 191 int cancel_point; 192 int cancel_async; 193 int cancel_enable; 194 int in_sigsuspend; 195 int err; 196 197 /* add previous level mask */ 198 SIGSETOR(actp->sa_mask, ucp->uc_sigmask); 199 200 /* add this signal's mask */ 201 if (!(actp->sa_flags & SA_NODEFER)) 202 SIGADDSET(actp->sa_mask, sig); 203 204 in_sigsuspend = curthread->in_sigsuspend; 205 curthread->in_sigsuspend = 0; 206 207 /* 208 * if thread is in deferred cancellation mode, disable cancellation 209 * in signal handler. 210 * if user signal handler calls a cancellation point function, e.g, 211 * it calls write() to write data to file, because write() is a 212 * cancellation point, the thread is immediately cancelled if 213 * cancellation is pending, to avoid this problem while thread is in 214 * deferring mode, cancellation is temporarily disabled. 215 */ 216 cancel_defer = curthread->cancel_defer; 217 cancel_point = curthread->cancel_point; 218 cancel_async = curthread->cancel_async; 219 cancel_enable = curthread->cancel_enable; 220 curthread->cancel_point = 0; 221 curthread->cancel_defer = 0; 222 if (!cancel_async) 223 curthread->cancel_enable = 0; 224 225 /* restore correct mask before calling user handler */ 226 __sys_sigprocmask(SIG_SETMASK, &actp->sa_mask, NULL); 227 228 sigfunc = actp->sa_sigaction; 229 230 /* 231 * We have already reset cancellation point flags, so if user's code 232 * longjmp()s out of its signal handler, wish its jmpbuf was set 233 * outside of a cancellation point, in most cases, this would be 234 * true. however, ther is no way to save cancel_enable in jmpbuf, 235 * so after setjmps() returns once more, the user code may need to 236 * re-set cancel_enable flag by calling pthread_setcancelstate(). 237 */ 238 if ((actp->sa_flags & SA_SIGINFO) != 0) 239 (*(sigfunc))(sig, info, ucp); 240 else { 241 ((ohandler)(*sigfunc))( 242 sig, info->si_code, (struct sigcontext *)ucp, 243 info->si_addr, (__sighandler_t *)sigfunc); 244 } 245 err = errno; 246 247 curthread->in_sigsuspend = in_sigsuspend; 248 curthread->cancel_defer = cancel_defer; 249 curthread->cancel_point = cancel_point; 250 curthread->cancel_enable = cancel_enable; 251 252 memcpy(&uc2, ucp, sizeof(uc2)); 253 SIGDELSET(uc2.uc_sigmask, SIGCANCEL); 254 255 /* reschedule cancellation */ 256 check_cancel(curthread, &uc2); 257 errno = err; 258 __sys_sigreturn(&uc2); 259} 260 |
|
97void 98_thr_ast(struct pthread *curthread) 99{ 100 | 261void 262_thr_ast(struct pthread *curthread) 263{ 264 |
101 if (THR_IN_CRITICAL(curthread)) | 265 if (!THR_IN_CRITICAL(curthread)) { 266 check_deferred_signal(curthread); 267 check_suspend(curthread); 268 check_cancel(curthread, NULL); 269 } 270} 271 272/* reschedule cancellation */ 273static void 274check_cancel(struct pthread *curthread, ucontext_t *ucp) 275{ 276 277 if (__predict_true(!curthread->cancel_pending || !curthread->cancel_enable || 278 curthread->cancelling)) |
102 return; 103 | 279 return; 280 |
104 if (curthread->cancel_pending && curthread->cancel_enable 105 && !curthread->cancelling) { 106 if (curthread->cancel_async) { 107 /* 108 * asynchronous cancellation mode, act upon 109 * immediately. 110 */ 111 _pthread_exit(PTHREAD_CANCELED); 112 } else { 113 /* 114 * Otherwise, we are in defer mode, and we are at 115 * cancel point, tell kernel to not block the current 116 * thread on next cancelable system call. 117 * 118 * There are two cases we should call thr_wake() to 119 * turn on TDP_WAKEUP in kernel: 120 * 1) we are going to call a cancelable system call, 121 * non-zero cancel_point means we are already in 122 * cancelable state, next system call is cancelable. 123 * 2) because _thr_ast() may be called by 124 * THR_CRITICAL_LEAVE() which is used by rtld rwlock 125 * and any libthr internal locks, when rtld rwlock 126 * is used, it is mostly caused my an unresolved PLT. 127 * those routines may clear the TDP_WAKEUP flag by 128 * invoking some system calls, in those cases, we 129 * also should reenable the flag. 130 */ 131 if (curthread->cancel_point) { 132 if (curthread->cancel_defer) 133 thr_wake(curthread->tid); 134 else 135 _pthread_exit(PTHREAD_CANCELED); 136 } | 281 if (curthread->cancel_async) { 282 /* 283 * asynchronous cancellation mode, act upon 284 * immediately. 285 */ 286 _pthread_exit_mask(PTHREAD_CANCELED, 287 ucp? &ucp->uc_sigmask : NULL); 288 } else { 289 /* 290 * Otherwise, we are in defer mode, and we are at 291 * cancel point, tell kernel to not block the current 292 * thread on next cancelable system call. 293 * 294 * There are three cases we should call thr_wake() to 295 * turn on TDP_WAKEUP or send SIGCANCEL in kernel: 296 * 1) we are going to call a cancelable system call, 297 * non-zero cancel_point means we are already in 298 * cancelable state, next system call is cancelable. 299 * 2) because _thr_ast() may be called by 300 * THR_CRITICAL_LEAVE() which is used by rtld rwlock 301 * and any libthr internal locks, when rtld rwlock 302 * is used, it is mostly caused my an unresolved PLT. 303 * those routines may clear the TDP_WAKEUP flag by 304 * invoking some system calls, in those cases, we 305 * also should reenable the flag. 306 * 3) thread is in sigsuspend(), and the syscall insists 307 * on getting a signal before it agrees to return. 308 */ 309 if (curthread->cancel_point) { 310 if (curthread->in_sigsuspend && ucp) { 311 SIGADDSET(ucp->uc_sigmask, SIGCANCEL); 312 curthread->unblock_sigcancel = 1; 313 _thr_send_sig(curthread, SIGCANCEL); 314 } else 315 thr_wake(curthread->tid); |
137 } 138 } | 316 } 317 } |
318} |
|
139 | 319 |
140 if (__predict_false((curthread->flags & 141 (THR_FLAGS_NEED_SUSPEND | THR_FLAGS_SUSPENDED)) 142 == THR_FLAGS_NEED_SUSPEND)) 143 _thr_suspend_check(curthread); | 320static void 321check_deferred_signal(struct pthread *curthread) 322{ 323 ucontext_t uc; 324 struct sigaction act; 325 siginfo_t info; 326 volatile int first; 327 328 if (__predict_true(curthread->deferred_siginfo.si_signo == 0)) 329 return; 330 first = 1; 331 getcontext(&uc); 332 if (first) { 333 first = 0; 334 act = curthread->deferred_sigact; 335 uc.uc_sigmask = curthread->deferred_sigmask; 336 memcpy(&info, &curthread->deferred_siginfo, sizeof(siginfo_t)); 337 /* remove signal */ 338 curthread->deferred_siginfo.si_signo = 0; 339 if (act.sa_flags & SA_RESETHAND) { 340 struct sigaction tact; 341 342 tact = act; 343 tact.sa_handler = SIG_DFL; 344 _sigaction(info.si_signo, &tact, NULL); 345 } 346 handle_signal(&act, info.si_signo, &info, &uc); 347 } |
144} 145 | 348} 349 |
146void 147_thr_suspend_check(struct pthread *curthread) | 350static void 351check_suspend(struct pthread *curthread) |
148{ 149 uint32_t cycle; | 352{ 353 uint32_t cycle; |
150 int err; | |
151 | 354 |
355 if (__predict_true((curthread->flags & 356 (THR_FLAGS_NEED_SUSPEND | THR_FLAGS_SUSPENDED)) 357 != THR_FLAGS_NEED_SUSPEND)) 358 return; 359 |
|
152 if (curthread->force_exit) 153 return; 154 | 360 if (curthread->force_exit) 361 return; 362 |
155 err = errno; | |
156 /* 157 * Blocks SIGCANCEL which other threads must send. 158 */ 159 _thr_signal_block(curthread); 160 161 /* 162 * Increase critical_count, here we don't use THR_LOCK/UNLOCK 163 * because we are leaf code, we don't want to recursively call --- 19 unchanged lines hidden (view full) --- 183 THR_UMUTEX_UNLOCK(curthread, &(curthread)->lock); 184 _thr_umtx_wait_uint(&curthread->cycle, cycle, NULL, 0); 185 THR_UMUTEX_LOCK(curthread, &(curthread)->lock); 186 curthread->flags &= ~THR_FLAGS_SUSPENDED; 187 } 188 THR_UMUTEX_UNLOCK(curthread, &(curthread)->lock); 189 curthread->critical_count--; 190 | 363 /* 364 * Blocks SIGCANCEL which other threads must send. 365 */ 366 _thr_signal_block(curthread); 367 368 /* 369 * Increase critical_count, here we don't use THR_LOCK/UNLOCK 370 * because we are leaf code, we don't want to recursively call --- 19 unchanged lines hidden (view full) --- 390 THR_UMUTEX_UNLOCK(curthread, &(curthread)->lock); 391 _thr_umtx_wait_uint(&curthread->cycle, cycle, NULL, 0); 392 THR_UMUTEX_LOCK(curthread, &(curthread)->lock); 393 curthread->flags &= ~THR_FLAGS_SUSPENDED; 394 } 395 THR_UMUTEX_UNLOCK(curthread, &(curthread)->lock); 396 curthread->critical_count--; 397 |
191 /* 192 * Unblocks SIGCANCEL, it is possible a new SIGCANCEL is ready and 193 * a new signal frame will nest us, this seems a problem because 194 * stack will grow and overflow, but because kernel will automatically 195 * mask the SIGCANCEL when delivering the signal, so we at most only 196 * have one nesting signal frame, this should be fine. 197 */ | |
198 _thr_signal_unblock(curthread); | 398 _thr_signal_unblock(curthread); |
199 errno = err; | |
200} 201 202void 203_thr_signal_init(void) 204{ 205 struct sigaction act; 206 | 399} 400 401void 402_thr_signal_init(void) 403{ 404 struct sigaction act; 405 |
207 /* Install cancel handler. */ 208 SIGEMPTYSET(act.sa_mask); 209 act.sa_flags = SA_SIGINFO | SA_RESTART; | 406 /* Install SIGCANCEL handler. */ 407 SIGFILLSET(act.sa_mask); 408 act.sa_flags = SA_SIGINFO; |
210 act.sa_sigaction = (__siginfohandler_t *)&sigcancel_handler; 211 __sys_sigaction(SIGCANCEL, &act, NULL); | 409 act.sa_sigaction = (__siginfohandler_t *)&sigcancel_handler; 410 __sys_sigaction(SIGCANCEL, &act, NULL); |
411 412 /* Unblock SIGCANCEL */ 413 SIGEMPTYSET(act.sa_mask); 414 SIGADDSET(act.sa_mask, SIGCANCEL); 415 __sys_sigprocmask(SIG_UNBLOCK, &act.sa_mask, NULL); |
|
212} 213 | 416} 417 |
418/* 419 * called from rtld with rtld_lock locked, because rtld_lock is 420 * a critical region, so all signals have already beeen masked. 421 */ |
|
214void | 422void |
423_thr_sigact_unload(struct dl_phdr_info *phdr_info) 424{ 425 struct urwlock *rwlp; 426 struct sigaction *actp; 427 struct sigaction kact; 428 void (*handler)(int); 429 int sig; 430 431 for (sig = 1; sig < _SIG_MAXSIG; sig++) { 432 actp = &_thr_sigact[sig].sigact; 433retry: 434 handler = actp->sa_handler; 435 if (handler != SIG_DFL && handler != SIG_IGN && 436 __elf_phdr_match_addr(phdr_info, handler)) { 437 rwlp = &_thr_sigact[sig].lock; 438 _thr_rwl_wrlock(rwlp); 439 if (handler != actp->sa_handler) { 440 _thr_rwl_unlock(rwlp); 441 goto retry; 442 } 443 actp->sa_handler = SIG_DFL; 444 actp->sa_flags = SA_SIGINFO; 445 SIGEMPTYSET(actp->sa_mask); 446 if (__sys_sigaction(sig, NULL, &kact) == 0 && 447 kact.sa_handler != SIG_DFL && 448 kact.sa_handler != SIG_IGN) 449 __sys_sigaction(sig, actp, NULL); 450 _thr_rwl_unlock(rwlp); 451 } 452 } 453} 454 455void 456_thr_signal_prefork(void) 457{ 458 int i; 459 460 for (i = 1; i < _SIG_MAXSIG; ++i) 461 _thr_rwl_rdlock(&_thr_sigact[i-1].lock); 462} 463 464void 465_thr_signal_postfork(void) 466{ 467 int i; 468 469 for (i = 1; i < _SIG_MAXSIG; ++i) 470 _thr_rwl_unlock(&_thr_sigact[i-1].lock); 471} 472 473void 474_thr_signal_postfork_child(void) 475{ 476 int i; 477 478 for (i = 1; i < _SIG_MAXSIG; ++i) 479 bzero(&_thr_sigact[i-1].lock, sizeof(struct urwlock)); 480} 481 482void |
|
215_thr_signal_deinit(void) 216{ 217} 218 219__weak_reference(___pause, pause); 220 221int 222___pause(void) 223{ | 483_thr_signal_deinit(void) 484{ 485} 486 487__weak_reference(___pause, pause); 488 489int 490___pause(void) 491{ |
224 struct pthread *curthread = _get_curthread(); 225 int ret; | 492 sigset_t oset; |
226 | 493 |
227 _thr_cancel_enter(curthread); 228 ret = __pause(); 229 _thr_cancel_leave(curthread); 230 231 return ret; | 494 if (_sigprocmask(SIG_BLOCK, NULL, &oset) == -1) 495 return (-1); 496 return (__sigsuspend(&oset)); |
232} 233 234__weak_reference(_raise, raise); 235 236int 237_raise(int sig) 238{ | 497} 498 499__weak_reference(_raise, raise); 500 501int 502_raise(int sig) 503{ |
239 int ret; 240 241 if (!_thr_isthreaded()) 242 ret = kill(getpid(), sig); 243 else 244 ret = _thr_send_sig(_get_curthread(), sig); 245 return (ret); | 504 return _thr_send_sig(_get_curthread(), sig); |
246} 247 248__weak_reference(_sigaction, sigaction); 249 250int 251_sigaction(int sig, const struct sigaction * act, struct sigaction * oact) 252{ | 505} 506 507__weak_reference(_sigaction, sigaction); 508 509int 510_sigaction(int sig, const struct sigaction * act, struct sigaction * oact) 511{ |
253 /* Check if the signal number is out of range: */ | 512 struct sigaction newact, oldact, oldact2; 513 sigset_t oldset; 514 int ret = 0, err = 0; 515 |
254 if (!_SIG_VALID(sig) || sig == SIGCANCEL) { | 516 if (!_SIG_VALID(sig) || sig == SIGCANCEL) { |
255 /* Return an invalid argument: */ | |
256 errno = EINVAL; 257 return (-1); 258 } 259 | 517 errno = EINVAL; 518 return (-1); 519 } 520 |
260 return __sys_sigaction(sig, act, oact); | 521 if (act) 522 newact = *act; 523 524 __sys_sigprocmask(SIG_SETMASK, &_thr_maskset, &oldset); 525 _thr_rwl_wrlock(&_thr_sigact[sig-1].lock); 526 527 if (act != NULL) { 528 oldact2 = _thr_sigact[sig-1].sigact; 529 530 /* 531 * if a new sig handler is SIG_DFL or SIG_IGN, 532 * don't remove old handler from _thr_sigact[], 533 * so deferred signals still can use the handlers, 534 * multiple threads invoking sigaction itself is 535 * a race condition, so it is not a problem. 536 */ 537 if (newact.sa_handler != SIG_DFL && 538 newact.sa_handler != SIG_IGN) { 539 _thr_sigact[sig-1].sigact = newact; 540 remove_thr_signals( 541 &_thr_sigact[sig-1].sigact.sa_mask); 542 newact.sa_flags &= ~SA_NODEFER; 543 newact.sa_flags |= SA_SIGINFO; 544 newact.sa_sigaction = thr_sighandler; 545 newact.sa_mask = _thr_maskset; /* mask all signals */ 546 } 547 if ((ret = __sys_sigaction(sig, &newact, &oldact))) { 548 err = errno; 549 _thr_sigact[sig-1].sigact = oldact2; 550 } 551 } else if (oact != NULL) { 552 ret = __sys_sigaction(sig, NULL, &oldact); 553 err = errno; 554 } 555 556 if (oldact.sa_handler != SIG_DFL && 557 oldact.sa_handler != SIG_IGN) { 558 oldact = _thr_sigact[sig-1].sigact; 559 } 560 561 _thr_rwl_unlock(&_thr_sigact[sig-1].lock); 562 __sys_sigprocmask(SIG_SETMASK, &oldset, NULL); 563 564 if (ret == 0) { 565 if (oact != NULL) 566 *oact = oldact; 567 } else { 568 errno = err; 569 } 570 return (ret); |
261} 262 263__weak_reference(_sigprocmask, sigprocmask); 264 265int 266_sigprocmask(int how, const sigset_t *set, sigset_t *oset) 267{ 268 const sigset_t *p = set; --- 27 unchanged lines hidden (view full) --- 296 sigset_t newset; 297 298 return (__sys_sigsuspend(thr_remove_thr_signals(set, &newset))); 299} 300 301int 302__sigsuspend(const sigset_t * set) 303{ | 571} 572 573__weak_reference(_sigprocmask, sigprocmask); 574 575int 576_sigprocmask(int how, const sigset_t *set, sigset_t *oset) 577{ 578 const sigset_t *p = set; --- 27 unchanged lines hidden (view full) --- 606 sigset_t newset; 607 608 return (__sys_sigsuspend(thr_remove_thr_signals(set, &newset))); 609} 610 611int 612__sigsuspend(const sigset_t * set) 613{ |
304 struct pthread *curthread = _get_curthread(); | 614 struct pthread *curthread; |
305 sigset_t newset; | 615 sigset_t newset; |
306 int ret; | 616 int ret, old; |
307 | 617 |
618 curthread = _get_curthread(); 619 620 old = curthread->in_sigsuspend; 621 curthread->in_sigsuspend = 1; |
|
308 _thr_cancel_enter(curthread); 309 ret = __sys_sigsuspend(thr_remove_thr_signals(set, &newset)); | 622 _thr_cancel_enter(curthread); 623 ret = __sys_sigsuspend(thr_remove_thr_signals(set, &newset)); |
310 _thr_cancel_leave(curthread); | 624 _thr_cancel_leave(curthread, 1); 625 curthread->in_sigsuspend = old; 626 if (curthread->unblock_sigcancel) { 627 curthread->unblock_sigcancel = 0; 628 SIGEMPTYSET(newset); 629 SIGADDSET(newset, SIGCANCEL); 630 __sys_sigprocmask(SIG_UNBLOCK, &newset, NULL); 631 } |
311 312 return (ret); 313} 314 315__weak_reference(__sigwait, sigwait); 316__weak_reference(__sigtimedwait, sigtimedwait); 317__weak_reference(__sigwaitinfo, sigwaitinfo); 318 --- 15 unchanged lines hidden (view full) --- 334int 335__sigtimedwait(const sigset_t *set, siginfo_t *info, 336 const struct timespec * timeout) 337{ 338 struct pthread *curthread = _get_curthread(); 339 sigset_t newset; 340 int ret; 341 | 632 633 return (ret); 634} 635 636__weak_reference(__sigwait, sigwait); 637__weak_reference(__sigtimedwait, sigtimedwait); 638__weak_reference(__sigwaitinfo, sigwaitinfo); 639 --- 15 unchanged lines hidden (view full) --- 655int 656__sigtimedwait(const sigset_t *set, siginfo_t *info, 657 const struct timespec * timeout) 658{ 659 struct pthread *curthread = _get_curthread(); 660 sigset_t newset; 661 int ret; 662 |
342 _thr_cancel_enter_defer(curthread, 1); | 663 _thr_cancel_enter(curthread); |
343 ret = __sys_sigtimedwait(thr_remove_thr_signals(set, &newset), info, 344 timeout); | 664 ret = __sys_sigtimedwait(thr_remove_thr_signals(set, &newset), info, 665 timeout); |
345 _thr_cancel_leave_defer(curthread, (ret == -1)); | 666 _thr_cancel_leave(curthread, (ret == -1)); |
346 return (ret); 347} 348 349int 350_sigwaitinfo(const sigset_t *set, siginfo_t *info) 351{ 352 sigset_t newset; 353 --- 7 unchanged lines hidden (view full) --- 361 */ 362int 363__sigwaitinfo(const sigset_t *set, siginfo_t *info) 364{ 365 struct pthread *curthread = _get_curthread(); 366 sigset_t newset; 367 int ret; 368 | 667 return (ret); 668} 669 670int 671_sigwaitinfo(const sigset_t *set, siginfo_t *info) 672{ 673 sigset_t newset; 674 --- 7 unchanged lines hidden (view full) --- 682 */ 683int 684__sigwaitinfo(const sigset_t *set, siginfo_t *info) 685{ 686 struct pthread *curthread = _get_curthread(); 687 sigset_t newset; 688 int ret; 689 |
369 _thr_cancel_enter_defer(curthread, 1); | 690 _thr_cancel_enter(curthread); |
370 ret = __sys_sigwaitinfo(thr_remove_thr_signals(set, &newset), info); | 691 ret = __sys_sigwaitinfo(thr_remove_thr_signals(set, &newset), info); |
371 _thr_cancel_leave_defer(curthread, ret == -1); | 692 _thr_cancel_leave(curthread, ret == -1); |
372 return (ret); 373} 374 375int 376_sigwait(const sigset_t *set, int *sig) 377{ 378 sigset_t newset; 379 --- 7 unchanged lines hidden (view full) --- 387 */ 388int 389__sigwait(const sigset_t *set, int *sig) 390{ 391 struct pthread *curthread = _get_curthread(); 392 sigset_t newset; 393 int ret; 394 | 693 return (ret); 694} 695 696int 697_sigwait(const sigset_t *set, int *sig) 698{ 699 sigset_t newset; 700 --- 7 unchanged lines hidden (view full) --- 708 */ 709int 710__sigwait(const sigset_t *set, int *sig) 711{ 712 struct pthread *curthread = _get_curthread(); 713 sigset_t newset; 714 int ret; 715 |
395 _thr_cancel_enter_defer(curthread, 1); | 716 _thr_cancel_enter(curthread); |
396 ret = __sys_sigwait(thr_remove_thr_signals(set, &newset), sig); | 717 ret = __sys_sigwait(thr_remove_thr_signals(set, &newset), sig); |
397 _thr_cancel_leave_defer(curthread, (ret != 0)); | 718 _thr_cancel_leave(curthread, (ret != 0)); |
398 return (ret); 399} 400 401__weak_reference(_setcontext, setcontext); 402int 403_setcontext(const ucontext_t *ucp) 404{ 405 ucontext_t uc; 406 | 719 return (ret); 720} 721 722__weak_reference(_setcontext, setcontext); 723int 724_setcontext(const ucontext_t *ucp) 725{ 726 ucontext_t uc; 727 |
407 (void) memcpy(&uc, ucp, sizeof (uc)); | 728 (void) memcpy(&uc, ucp, sizeof(uc)); |
408 remove_thr_signals(&uc.uc_sigmask); | 729 remove_thr_signals(&uc.uc_sigmask); |
409 | |
410 return __sys_setcontext(&uc); 411} 412 413__weak_reference(_swapcontext, swapcontext); 414int 415_swapcontext(ucontext_t *oucp, const ucontext_t *ucp) 416{ 417 ucontext_t uc; 418 | 730 return __sys_setcontext(&uc); 731} 732 733__weak_reference(_swapcontext, swapcontext); 734int 735_swapcontext(ucontext_t *oucp, const ucontext_t *ucp) 736{ 737 ucontext_t uc; 738 |
419 (void) memcpy(&uc, ucp, sizeof (uc)); | 739 (void) memcpy(&uc, ucp, sizeof(uc)); |
420 remove_thr_signals(&uc.uc_sigmask); 421 return __sys_swapcontext(oucp, &uc); 422} | 740 remove_thr_signals(&uc.uc_sigmask); 741 return __sys_swapcontext(oucp, &uc); 742} |