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)
|
int sigsuspend(FAR const sigset_t *set)
|
||||||
{
|
{
|
||||||
FAR struct tcb_s *rtcb = this_task();
|
FAR struct tcb_s *rtcb = this_task();
|
||||||
sigset_t intersection;
|
|
||||||
sigset_t saved_sigprocmask;
|
sigset_t saved_sigprocmask;
|
||||||
FAR sigpendq_t *sigpend;
|
|
||||||
irqstate_t flags;
|
irqstate_t flags;
|
||||||
int unblocksigno;
|
|
||||||
|
|
||||||
/* sigsuspend() is a cancellation point */
|
/* sigsuspend() is a cancellation point */
|
||||||
|
|
||||||
@ -112,36 +109,30 @@ int sigsuspend(FAR const sigset_t *set)
|
|||||||
sched_lock(); /* Not necessary */
|
sched_lock(); /* Not necessary */
|
||||||
flags = enter_critical_section();
|
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
|
/* Check if there is a pending signal corresponding to one of the
|
||||||
* signals that will be unblocked by the new sigprocmask.
|
* signals that will be unblocked by the new sigprocmask.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
intersection = ~(*set) & nxsig_pendingset(rtcb);
|
if (nxsig_unmask_pendingsignal())
|
||||||
if (intersection != NULL_SIGNAL_SET)
|
|
||||||
{
|
{
|
||||||
/* One or more of the signals in intersections is sufficient to cause
|
/* Dispatching one or more of the signals is sufficient to cause
|
||||||
* us to not wait. Pick the lowest numbered signal and mark it not
|
* us to not wait. Restore the original sigprocmask.
|
||||||
* pending.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
unblocksigno = nxsig_lowest(&intersection);
|
rtcb->sigprocmask = saved_sigprocmask;
|
||||||
sigpend = nxsig_remove_pendingsignal(rtcb, unblocksigno);
|
|
||||||
DEBUGASSERT(sigpend);
|
|
||||||
|
|
||||||
nxsig_release_pendingsignal(sigpend);
|
|
||||||
leave_critical_section(flags);
|
leave_critical_section(flags);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Its time to wait. Save a copy of the old sigprocmask and install
|
/* Its time to wait until one of the unblocked signals is posted */
|
||||||
* 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 */
|
|
||||||
|
|
||||||
up_block_task(rtcb, TSTATE_WAIT_SIG);
|
up_block_task(rtcb, TSTATE_WAIT_SIG);
|
||||||
|
|
||||||
@ -160,5 +151,6 @@ int sigsuspend(FAR const sigset_t *set)
|
|||||||
|
|
||||||
sched_unlock();
|
sched_unlock();
|
||||||
leave_cancellation_point();
|
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();
|
FAR struct tcb_s *rtcb = this_task();
|
||||||
sigset_t unmaskedset;
|
sigset_t unmaskedset;
|
||||||
@ -79,10 +79,15 @@ void nxsig_unmask_pendingsignal(void)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
unmaskedset = ~(rtcb->sigprocmask) & nxsig_pendingset(rtcb);
|
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. */
|
/* 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
|
/* Pending signals will be processed from lowest numbered signal
|
||||||
* to highest
|
* to highest
|
||||||
@ -117,7 +122,9 @@ void nxsig_unmask_pendingsignal(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
while (unmaskedset != NULL_SIGNAL_SET);
|
||||||
|
|
||||||
sched_unlock();
|
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_pendingsigaction(FAR sigq_t *sigq);
|
||||||
void nxsig_release_pendingsignal(FAR sigpendq_t *sigpend);
|
void nxsig_release_pendingsignal(FAR sigpendq_t *sigpend);
|
||||||
FAR sigpendq_t *nxsig_remove_pendingsignal(FAR struct tcb_s *stcb, int signo);
|
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 */
|
#endif /* __SCHED_SIGNAL_SIGNAL_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user