恢复Lua线程时如何处理错误(coroutine)

背景:我正在使用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中的产量(虽然5.2可能是一个很好的解决方案)。 通过lua_resume调用,我在会话中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,您可以使用coxpcall 。

据我所知,抛出一个错误会解开协同程序中的堆栈,这意味着没有函数可以跳回。 (参考手册对此没有任何说明。)

好像你必须创建一个新线程。