c -在恢复一个Lua线程(协程)时如何处理错误



Background:我使用一个Lua线程(协程)来处理来自stdin的用户输入(允许程序在等待来自另一个FD的数据时暂停)。因为它是用户输入,所以即使不太可能,也可能出现错误,例如调用一个不存在的函数。

问题:可以恢复Lua线程,以便我可以继续处理更多的数据从stdin,或者我必须核线程,并在每次错误后创建一个新的?

这里是我现在所做的一些粗略的示例/伪代码:

while (1) {
  select((max, &read_fds, &write_fds, NULL, NULL);
  for each file descriptor {
    if (read fd is set) {
      read data into a buffer
      if (current fd is stdin)
        process_stdin()
      else if (current fd is from server connection)
        process_remote()
    }
    if (write fd is set) {
      write data on non-blocking fd
    }
  }
}
process_stdin() {
  status=luaL_loadbuffer(L, stdin_buf, len, "stdin");
  if (status == LUA_ERRSYNTAX) {
    /* handle EOF which means more user input needed
     * or print error message for user, this works fine */
  }
  else if (status == 0) {
    status=lua_resume(L, 0);
    if (status != 0 && status != LUA_YIELD) {
      /* Do I nuke the thread or is there another way to recover at this point??? */
    }
  }
}

通常,我会使用pcall来捕获错误并恢复,但是pcall不支持5.1中的yield(尽管这里5.2可能是一个很好的解决方案)。使用lua_resume呼叫,我在会话中遇到以下情况:

> no_such_func()
Error: attempt to call global 'no_such_func' (a nil value)
> print("hello world")
Error: cannot resume non-suspended coroutine

执行第一个命令后,线程状态设置为2 (LUA_ERRRUN)。

编辑:我得到的错误信息似乎不是因为未展开的堆栈。我从ldo.c中看到这条消息,表明问题是因为线程状态被设置为2。

  if (L->status != LUA_YIELD && (L->status != 0 || L->ci != L->base_ci))
      return resume_error(L, "cannot resume non-suspended coroutine");

所以我要么需要一种重置状态的方法,要么一开始就避免状态改变。我的猜测是,我可能会从主堆栈中弹出线程并重新创建一个新的线程,或者升级到5.2,以便我可以从pcall中生成。

据我所知,抛出错误会打开协程内的堆栈,这意味着没有可以跳转回的函数。(参考手册没有提到这一点)

似乎你必须创建一个新的线程

对于Lua 5.1,您可以使用coxcall .

相关内容

最新更新