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

window_manager_default_close_window 关闭窗口死循环问题 #872

Open
BRUCEYANGGK opened this issue Mar 12, 2024 · 7 comments
Open

window_manager_default_close_window 关闭窗口死循环问题 #872

BRUCEYANGGK opened this issue Mar 12, 2024 · 7 comments

Comments

@BRUCEYANGGK
Copy link

最近开发过程中发现在执行window_manager_default_close_window函数的时候会触发条件走到以下分支,然后死循环,想问一下这段代码的意义,看上去只要条件成立就是死循环,是否可以删除
if (!window_is_opened(window)) {
uint32_t idle_id = widget_get_prop_int(window, "check_and_close_window_idle_id", 0);
if (idle_id == 0) {
idle_id = widget_add_idle(window, window_manager_default_on_idle_check_and_close_window);
widget_set_prop_int(window, "check_and_close_window_idle_id", idle_id);
}
return RET_OK;
}

@xianjimli
Copy link
Member

不会死循环啊。如果窗口还没打开就异步关闭。

@BRUCEYANGGK
Copy link
Author

BRUCEYANGGK commented Mar 12, 2024

异步关闭是指idle的回调函数吗,因为我这里遇到一个awtk卡死的问题,最后看coredump结果是卡在这一行,而且复现的概率比较低,我想知道如果窗口还没有打开的话,进入到这个分支,然后idle定时器的回调函数还是调用的window_manager_close_window函数,这中间没有其他处理,是不是会一直循环下去?

static ret_t window_manager_default_on_idle_check_and_close_window(const idle_info_t* idle) {
widget_t* win = WIDGET(idle->ctx);
window_manager_close_window(window_manager(), win);
return RET_REPEAT;
}

@xianjimli
Copy link
Member

方便的话,你弄个可以重现的demo给我看看。

@BRUCEYANGGK
Copy link
Author

我这里也就复现了两次,看上去都和close_all 有关,代码是参考的window_manager_close_all这个函数,但是把里面的window_manager_close_window_force改成window_close(win) 类似于下面这样

ret_t window_manager_close_all(widget_t* widget) {
return_value_if_fail(widget != NULL, RET_BAD_PARAMS);

do {
uint32_t nr = widget_count_children(widget);
if (nr > 0) {
widget_t* win = widget_get_child(widget, nr - 1);
window_close(win);
} else {
break;
}
} while (TRUE);

return RET_OK;
}

功能就是将之前的页面关闭然后打开新的页面,在点击按钮关闭的时候就有很小的概率会陷入死循环
我手动生成coredump后发现调用栈卡在这一行,看awtk源码后分析觉得可能是在window_manager_default_close_window这里面
if (!window_is_opened(window))这个条件成立了,但是没找到必现的方法,然后我看代码如果走进这个分支的话好像是会陷入死循环,尝试将if (!window_is_opened(window))这个条件改成ture,然后运行发现就是不停在idle里面回调卡死

@xianjimli
Copy link
Member

正常情况下,关闭还没有打开的窗口,第一次关闭失败,第二次会关闭成功,窗口被销毁,然后窗口相关的idle都会被移除掉,不会进入死循环。

@xianjimli
Copy link
Member

我改了一下,你更新试试,谢谢。

@BRUCEYANGGK
Copy link
Author

我昨天找到了必现方法,很抱歉是我之前的猜想是错误的,谢谢您帮忙跟进,卡死的原因是在do while循环里面不停地获取第一个elms, 然而调用window close 函数走到if (!window_is_opened(window))这个分支的时候,实际新窗口已经load上 ,但是状态还没到下一个主循环,所以状态还是WINDOW_STAGE_LOADED,这个时候会走到if (!window_is_opened(window))这个分支里面,然后不停的加idle定时器,实际是当前主循环一直卡死,没有走到下一个idle dispatch, 我当前的解决办法是修改window_is_opened(window)函数,放宽window_is_open的判断条件:具体修改如下:
static bool_t window_is_opened(widget_t* widget) {
int32_t stage = widget_get_prop_int(widget, WIDGET_PROP_STAGE, WINDOW_STAGE_NONE);

return stage != WINDOW_STAGE_CLOSED && stage != WINDOW_STAGE_NONE;
}
验证好像没有问题,不知道这样改会不会有什么隐患,请帮忙评估一下

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

2 participants