【问题标题】:Lua returning output after subprocessLua在子进程后返回输出
【发布时间】:2020-10-30 01:11:08
【问题描述】:

在 lua 中工作,我有一个键/值对表

local fmtsToRun = { 
  name = function() 
    return configSubTable
  end
}

长度可以是 1 个或多个条目。我需要遍历每个条目并运行一个子进程(通过一些 libuv C 绑定)。

对于正常的 for 循环,子进程会在循环完成运行后返回 libuv,导致出现乱序。结果是

  • 循环开始
  • 循环条目 1
  • 工作 1 开始
  • 循环条目 2
  • 工作 2 开始
  • 循环结束
  • Job1 返回
  • Job2 返回

我需要的是

  • 循环开始
  • 循环条目 1
  • 工作 1 开始
  • Job1 返回
  • 循环条目 2
  • 工作 2 开始
  • Job2 返回
  • 循环结束

我也尝试编写自己的pairs() 版本并使用协程之类的东西来处理回调


for fmt, output in jobIterator(fmtsToRun) do
  print('finished running', output)
end


  local function jobIterator(tbl)
    return coroutine.wrap(function()
      local fmtConf, fmtName
      fmtName, fmtConf = next(tbl, fmtName)
      if nil~=fmtConf then
          local conf = fmtConf()
          local output = nil
          -- wrapper util from Libuv library
          local job = Job:new({
              cmd = conf.cmd,
              args = conf.args,
              on_stdout = onStdout, -- process output
              on_stderr = onStderr, -- process any error
              on_exit = function()
                coroutine.yield(fmtName, output)
              end
          })
          job.send(conf.data)
      end
    end)
  end

这会导致此错误消息。

attempt to yield across C-call boundary

在保持正确顺序的同时等待job 完成并继续循环的“正确”方式是什么?

【问题讨论】:

  • 我只使用 os.execute() 而不是协程。这样,您就可以保证在开始新任务之前,当前流程将按所需顺序完成。

标签: lua libuv luvit


【解决方案1】:

更好的选择是手动控制流程并递归调用一个函数来逐个遍历表中的一个条目。

local runner = {}
for _, output in pairs(fmtsToRun) do
  table.insert(runner, output)
end
jobIterator(runner)

local function jobIterator(tbl)
  local F = {}
  function F.step()
    if #tbl == 0 then
      return
    end
    local current = table.remove(tbl, 1)
    F.run(current)
  end
  
  function F.run(conf)
    local output = nil
    -- wrapper util from Libuv library
    local job =
      Job:new(
      {
        cmd = conf.cmd,
        args = conf.args,
        on_stdout = onStdout, -- process output
        on_stderr = onStderr, -- process any error
        on_exit = function()
          -- do what you need with output
          print(output)
          F.step()
        end
      }
    )
    job.send(conf.data)
  end

  F.step()
end

【讨论】:

    猜你喜欢
    • 2017-05-29
    • 2012-01-18
    • 1970-01-01
    • 2015-09-25
    • 2018-05-01
    • 1970-01-01
    • 2021-03-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多