sched/signal/sig_suspend.c: sigsuspend() shouldn't eat the pending signal but dispatch all instead
This commit is contained in:
parent
acb83cfc61
commit
27c7974cb1
@ -93,11 +93,8 @@
|
||||
int sigsuspend(FAR const sigset_t *set)
|
||||
{
|
||||
FAR struct tcb_s *rtcb = this_task();
|
||||
sigset_t intersection;
|
||||
sigset_t saved_sigprocmask;
|
||||
FAR sigpendq_t *sigpend;
|
||||
irqstate_t flags;
|
||||
int unblocksigno;
|
||||
|
||||
/* sigsuspend() is a cancellation point */
|
||||
|
||||
@ -112,36 +109,30 @@ int sigsuspend(FAR const sigset_t *set)
|
||||
sched_lock(); /* Not necessary */
|
||||
flags = enter_critical_section();
|
||||
|
||||
/* Save a copy of the old sigprocmask and install
|
||||
* the new (temporary) sigprocmask
|
||||
*/
|
||||
|
||||
saved_sigprocmask = rtcb->sigprocmask;
|
||||
rtcb->sigprocmask = *set;
|
||||
rtcb->sigwaitmask = NULL_SIGNAL_SET;
|
||||
|
||||
/* Check if there is a pending signal corresponding to one of the
|
||||
* signals that will be unblocked by the new sigprocmask.
|
||||
*/
|
||||
|
||||
intersection = ~(*set) & nxsig_pendingset(rtcb);
|
||||
if (intersection != NULL_SIGNAL_SET)
|
||||
if (nxsig_unmask_pendingsignal())
|
||||
{
|
||||
/* One or more of the signals in intersections is sufficient to cause
|
||||
* us to not wait. Pick the lowest numbered signal and mark it not
|
||||
* pending.
|
||||
/* Dispatching one or more of the signals is sufficient to cause
|
||||
* us to not wait. Restore the original sigprocmask.
|
||||
*/
|
||||
|
||||
unblocksigno = nxsig_lowest(&intersection);
|
||||
sigpend = nxsig_remove_pendingsignal(rtcb, unblocksigno);
|
||||
DEBUGASSERT(sigpend);
|
||||
|
||||
nxsig_release_pendingsignal(sigpend);
|
||||
rtcb->sigprocmask = saved_sigprocmask;
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Its time to wait. Save a copy of the old sigprocmask and install
|
||||
* the new (temporary) sigprocmask
|
||||
*/
|
||||
|
||||
saved_sigprocmask = rtcb->sigprocmask;
|
||||
rtcb->sigprocmask = *set;
|
||||
rtcb->sigwaitmask = NULL_SIGNAL_SET;
|
||||
|
||||
/* And wait until one of the unblocked signals is posted */
|
||||
/* Its time to wait until one of the unblocked signals is posted */
|
||||
|
||||
up_block_task(rtcb, TSTATE_WAIT_SIG);
|
||||
|
||||
@ -160,5 +151,6 @@ int sigsuspend(FAR const sigset_t *set)
|
||||
|
||||
sched_unlock();
|
||||
leave_cancellation_point();
|
||||
return ERROR; /* ??REVISIT: Always returns ERROR?? */
|
||||
set_errno(EINTR);
|
||||
return ERROR;
|
||||
}
|
||||
|
@ -58,7 +58,7 @@
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void nxsig_unmask_pendingsignal(void)
|
||||
bool nxsig_unmask_pendingsignal(void)
|
||||
{
|
||||
FAR struct tcb_s *rtcb = this_task();
|
||||
sigset_t unmaskedset;
|
||||
@ -79,10 +79,15 @@ void nxsig_unmask_pendingsignal(void)
|
||||
*/
|
||||
|
||||
unmaskedset = ~(rtcb->sigprocmask) & nxsig_pendingset(rtcb);
|
||||
if (unmaskedset == NULL_SIGNAL_SET)
|
||||
{
|
||||
sched_unlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Loop while there are unmasked pending signals to be processed. */
|
||||
|
||||
while (unmaskedset != NULL_SIGNAL_SET)
|
||||
do
|
||||
{
|
||||
/* Pending signals will be processed from lowest numbered signal
|
||||
* to highest
|
||||
@ -117,7 +122,9 @@ void nxsig_unmask_pendingsignal(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
while (unmaskedset != NULL_SIGNAL_SET);
|
||||
|
||||
sched_unlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -215,6 +215,6 @@ int nxsig_mqnotempty(int tid, int signo, FAR void *sival_ptr);
|
||||
void nxsig_release_pendingsigaction(FAR sigq_t *sigq);
|
||||
void nxsig_release_pendingsignal(FAR sigpendq_t *sigpend);
|
||||
FAR sigpendq_t *nxsig_remove_pendingsignal(FAR struct tcb_s *stcb, int signo);
|
||||
void nxsig_unmask_pendingsignal(void);
|
||||
bool nxsig_unmask_pendingsignal(void);
|
||||
|
||||
#endif /* __SCHED_SIGNAL_SIGNAL_H */
|
||||
|
Loading…
Reference in New Issue
Block a user