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

标签 c lua

背景:我正在使用 Lua 线程(协程)处理来自标准输入的用户输入(以允许程序在等待来自另一个 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 调用,我在我的 session 中遇到了以下问题:

> 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 中退出。

最佳答案

据我所知,抛出错误会展开协程内部的堆栈,这意味着没有函数可以跳回。 (引用手册对此没有任何说明。)

看来您必须创建一个新线程。

关于c - 恢复 Lua 线程(协程)时如何处理错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6625698/

相关文章:

lua - 有指数运行时间的 Lua 病理模式吗?

function - lua中算术运算字符串的分割

C - 重定向的 open 函数未读取完整字符 'string'

c - 在 C 中分配浮点指针

c - sscanf() 将十六进制整数转换为整数数组与无符号字符

mysql - Lua脚本无法连接到MySQL数据库

c# - 在C#中嵌入一个Lua交互提示窗口

c# - LUA - '・ 附近出现意外符号

c - 从 uint8_t* 到 uint32_t 的转换无效 - 从 32 位架构迁移到 64 位架构时?

c - Backspace(\b) 不清除非规范模式 termios 中的文本