| 1525 | } |
| 1526 | |
| 1527 | int |
| 1528 | kern_sigsuspend(struct thread *td, sigset_t mask) |
| 1529 | { |
| 1530 | struct proc *p = td->td_proc; |
| 1531 | int has_sig, sig; |
| 1532 | |
| 1533 | /* Ensure the sigfastblock value is up to date. */ |
| 1534 | sigfastblock_fetch(td); |
| 1535 | |
| 1536 | /* |
| 1537 | * When returning from sigsuspend, we want |
| 1538 | * the old mask to be restored after the |
| 1539 | * signal handler has finished. Thus, we |
| 1540 | * save it here and mark the sigacts structure |
| 1541 | * to indicate this. |
| 1542 | */ |
| 1543 | PROC_LOCK(p); |
| 1544 | kern_sigprocmask(td, SIG_SETMASK, &mask, &td->td_oldsigmask, |
| 1545 | SIGPROCMASK_PROC_LOCKED); |
| 1546 | td->td_pflags |= TDP_OLDMASK; |
| 1547 | |
| 1548 | /* |
| 1549 | * Process signals now. Otherwise, we can get spurious wakeup |
| 1550 | * due to signal entered process queue, but delivered to other |
| 1551 | * thread. But sigsuspend should return only on signal |
| 1552 | * delivery. |
| 1553 | */ |
| 1554 | (p->p_sysent->sv_set_syscall_retval)(td, EINTR); |
| 1555 | for (has_sig = 0; !has_sig;) { |
| 1556 | while (msleep(&p->p_sigacts, &p->p_mtx, PPAUSE|PCATCH, "pause", |
| 1557 | 0) == 0) |
| 1558 | /* void */; |
| 1559 | thread_suspend_check(0); |
| 1560 | mtx_lock(&p->p_sigacts->ps_mtx); |
| 1561 | while ((sig = cursig(td)) != 0) { |
| 1562 | KASSERT(sig >= 0, ("sig %d", sig)); |
| 1563 | has_sig += postsig(sig); |
| 1564 | } |
| 1565 | mtx_unlock(&p->p_sigacts->ps_mtx); |
| 1566 | |
| 1567 | /* |
| 1568 | * If PTRACE_SCE or PTRACE_SCX were set after |
| 1569 | * userspace entered the syscall, return spurious |
| 1570 | * EINTR. |
| 1571 | */ |
| 1572 | if ((p->p_ptevents & PTRACE_SYSCALL) != 0) |
| 1573 | has_sig += 1; |
| 1574 | } |
| 1575 | PROC_UNLOCK(p); |
| 1576 | td->td_errno = EINTR; |
| 1577 | td->td_pflags |= TDP_NERRNO; |
| 1578 | return (EJUSTRETURN); |
| 1579 | } |
| 1580 | |
| 1581 | #ifdef COMPAT_43 /* XXX - COMPAT_FBSD3 */ |
| 1582 | /* |
no test coverage detected