Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tos_at.c的at_parser问题 #256

Open
John-J-smith opened this issue Dec 15, 2020 · 4 comments
Open

tos_at.c的at_parser问题 #256

John-J-smith opened this issue Dec 15, 2020 · 4 comments

Comments

@John-J-smith
Copy link

在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);
}
@Supowang1989
Copy link
Collaborator

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

@John-J-smith
Copy link
Author

您好,我是在实际项目中遇到的这个问题。场景如下:
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;
}

@daishengdong
Copy link
Collaborator

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

@huwt-lu
Copy link

huwt-lu commented Jan 11, 2022

我提问下,
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的操作需要原子保护

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants