[smart] Fix bugs on lwp kill (#7892)

Signed-off-by: Shell <smokewood@qq.com>
This commit is contained in:
Shell
2023-08-03 20:25:13 +08:00
committed by GitHub
parent e5c8dd3b05
commit 325c3d2a48
6 changed files with 82 additions and 54 deletions

View File

@@ -546,32 +546,36 @@ void lwp_thread_signal_catch(void *exp_frame)
* @note that the p_usi is release before entering signal action by
* reseting the kernel sp.
*/
LOG_D("%s: enter signal handler(signo=%d) at %p", __func__, signo, handler);
arch_thread_signal_enter(signo, p_usi, exp_frame, handler, &save_sig_mask);
/* the arch_thread_signal_enter() never return */
RT_ASSERT(0);
}
}
static int _do_signal_wakeup(rt_thread_t thread, int sig)
{
int need_schedule;
if ((thread->stat & RT_THREAD_SUSPEND_MASK) == RT_THREAD_SUSPEND_MASK)
if (!_sigismember(&thread->signal.sigset_mask, sig))
{
if ((thread->stat & RT_SIGNAL_COMMON_WAKEUP_MASK) != RT_SIGNAL_COMMON_WAKEUP_MASK)
if ((thread->stat & RT_THREAD_SUSPEND_MASK) == RT_THREAD_SUSPEND_MASK)
{
rt_thread_wakeup(thread);
need_schedule = 1;
}
else if ((sig == SIGKILL) && ((thread->stat & RT_SIGNAL_KILL_WAKEUP_MASK) != RT_SIGNAL_KILL_WAKEUP_MASK))
{
rt_thread_wakeup(thread);
need_schedule = 1;
if ((thread->stat & RT_SIGNAL_COMMON_WAKEUP_MASK) != RT_SIGNAL_COMMON_WAKEUP_MASK)
{
rt_thread_wakeup(thread);
need_schedule = 1;
}
else if ((sig == SIGKILL) && ((thread->stat & RT_SIGNAL_KILL_WAKEUP_MASK) != RT_SIGNAL_KILL_WAKEUP_MASK))
{
rt_thread_wakeup(thread);
need_schedule = 1;
}
else
{
need_schedule = 0;
}
}
else
{
need_schedule = 0;
}
}
else
need_schedule = 0;
@@ -633,7 +637,7 @@ static int _siginfo_deliver_to_lwp(struct rt_lwp *lwp, lwp_siginfo_t siginfo)
return _do_signal_wakeup(catcher, siginfo->ksiginfo.signo);
}
static int _siginfo_deliver_to_thread(struct rt_lwp *lwp, rt_thread_t thread, lwp_siginfo_t siginfo)
static int _siginfo_deliver_to_thread(rt_thread_t thread, lwp_siginfo_t siginfo)
{
sigqueue_enqueue(_SIGQ(thread), siginfo);
return _do_signal_wakeup(thread, siginfo->ksiginfo.signo);
@@ -679,6 +683,9 @@ rt_err_t lwp_signal_kill(struct rt_lwp *lwp, long signo, long code, long value)
}
else
{
LOG_D("%s(lwp=%p \"%s\",signo=%ld,code=%ld,value=%ld)",
__func__, lwp, lwp->cmd, signo, code, value);
need_schedule = RT_FALSE;
/* FIXME: acquire READ lock to lwp */
@@ -848,7 +855,7 @@ rt_err_t lwp_thread_signal_kill(rt_thread_t thread, long signo, long code, long
if (siginfo)
{
need_schedule = _siginfo_deliver_to_thread(lwp, thread, siginfo);
need_schedule = _siginfo_deliver_to_thread(thread, siginfo);
ret = 0;
}
else
@@ -943,10 +950,10 @@ static int _dequeue_signal(rt_thread_t thread, lwp_sigset_t *mask, siginfo_t *us
rt_err_t lwp_thread_signal_timedwait(rt_thread_t thread, lwp_sigset_t *sigset,
siginfo_t *usi, struct timespec *timeout)
{
LOG_D("%s", __func__);
rt_base_t level;
rt_err_t ret;
lwp_sigset_t saved_sigset;
lwp_sigset_t blocked_sigset;
int sig;
/**
@@ -960,6 +967,7 @@ rt_err_t lwp_thread_signal_timedwait(rt_thread_t thread, lwp_sigset_t *sigset,
_sigdelset(sigset, SIGSTOP);
_signotsets(sigset, sigset);
/* FIXME: acquire READ lock to lwp */
level = rt_hw_interrupt_disable();
sig = _dequeue_signal(thread, sigset, usi);
@@ -967,17 +975,19 @@ rt_err_t lwp_thread_signal_timedwait(rt_thread_t thread, lwp_sigset_t *sigset,
if (sig)
return sig;
/* WARNING atomic problem, what if pending signal arrives before we sleep */
/**
* @brief POSIX
* if none of the signals specified by set are pending, sigtimedwait() shall
* wait for the time interval specified in the timespec structure referenced
* by timeout.
*
* @note If the pending signal arrives before thread suspend, the suspend
* operation will return a failure
*/
_sigandsets(&blocked_sigset, &thread->signal.sigset_mask, sigset);
_thread_signal_mask(thread, LWP_SIG_MASK_CMD_SET_MASK, &blocked_sigset, &saved_sigset);
if (timeout)
{
/* TODO: verify timeout valid ? not overflow 32bits, nanosec valid, ... */
rt_uint32_t time;
time = rt_timespec_to_tick(timeout);
@@ -1006,9 +1016,14 @@ rt_err_t lwp_thread_signal_timedwait(rt_thread_t thread, lwp_sigset_t *sigset,
if (ret == RT_EOK)
{
rt_schedule();
ret = -EAGAIN;
/* If thread->error reliable? */
if (thread->error == -RT_EINTR)
ret = -EINTR;
else
ret = -EAGAIN;
}
/* else ret == -EINTR */
_thread_signal_mask(thread, LWP_SIG_MASK_CMD_SET_MASK, &saved_sigset, RT_NULL);
/* FIXME: acquire READ lock to lwp */
level = rt_hw_interrupt_disable();