TobudOS icon indicating copy to clipboard operation
TobudOS copied to clipboard

tos_at.c的at_parser问题

Open John-J-smith opened this issue 4 years ago • 4 comments

在at_parser的如下代码中,先释放了信号,后拷贝at_echo的buf,在这之间可能发生任务调度导致at_echo被提前释放而hardfault

if (at_parse_status == AT_PARSE_STATUS_EXPECT) {
    at_echo->status = AT_ECHO_STATUS_EXPECT;
    if (at_echo->__is_expecting) {
        tos_sem_post(&at_echo->__expect_notify);
    }
} else if (at_parse_status == AT_PARSE_STATUS_NEWLINE &&
        at_echo->status == AT_ECHO_STATUS_NONE) {
        at_echo_status_set(at_echo);
}

if (at_echo->buffer) {
    at_echo_buffer_copy(recv_cache, at_echo);
}

John-J-smith avatar Dec 15 '20 06:12 John-J-smith

您是实际遇到过因为这样hardfault的情况吗?能否提供问题复现的场景?

Supowang1989 avatar Dec 16 '20 02:12 Supowang1989

您好,我是在实际项目中遇到的这个问题。场景如下: 在at_parser任务中释放了at_echo->__expect_notify信号量,并且在at_echo_buffer_copy之前发生了任务调度,任务切换到了tos_at_cmd_exec_until中,成功获取了echo->__expect_notify信号量,随后执行了AT_AGENT->echo = K_NULL;,等任务再切换回at_parser时,at_echo已经为空,此时再拷贝就会出现hardfault。 将拷贝放到释放信号之前则不会出现该问题。

__STATIC__ void at_parser(void *arg)
{
    ...

        if (at_parse_status == AT_PARSE_STATUS_EXPECT) {
            at_echo->status = AT_ECHO_STATUS_EXPECT;
            if (at_echo->__is_expecting) {
                tos_sem_post(&at_echo->__expect_notify);
            }
        } else if (at_parse_status == AT_PARSE_STATUS_NEWLINE &&
                    at_echo->status == AT_ECHO_STATUS_NONE) {
            at_echo_status_set(at_echo);
        }

        if (at_echo->buffer) {
            at_echo_buffer_copy(recv_cache, at_echo);
        }

    ...
}

__API__ int tos_at_cmd_exec_until(at_echo_t *echo, uint32_t timeout, const char *cmd, ...)
{
    ...
    
    if (ret != 0) {
        AT_AGENT->echo = K_NULL;
        return -1;
    }

    if (tos_sem_pend(&echo->__expect_notify, tos_millisec2tick(timeout)) != K_ERR_NONE) {
        ret = -1;
    }

    tos_sem_destroy(&echo->__expect_notify);

    AT_AGENT->echo = K_NULL;

    return ret;
}

John-J-smith avatar Dec 17 '20 08:12 John-J-smith

这确实是一个问题,我提交一个bugfix。您那边可以暂时先把语句顺序调换一下,copy动作放到sem_post之前,应该可以规避这个问题。

daishengdong avatar Feb 05 '21 07:02 daishengdong

我提问下, tos_at_cmd_exec_until 和 at_parser 是两个不同的任务在同时操作 echo,如果 tos_at_cmd_exec_until 执行 tos_sem_pend超时,AT_AGENT->echo 直接被清空,如果这时候执行到 at_parser 对AT_AGENT->echode 操作,应该也会生成一个hardfault, 发生的条件需要执行到 if (!at_echo) 判断后,进行了tos_sem_pend超时引起的任务切换 AT_AGENT->echo被清空; 对于 if (!at_echo) 后的对于echo的操作需要原子保护

huwt-lu avatar Jan 11 '22 09:01 huwt-lu