Search code examples
lualibuv

how to use luv with pipes?


I am trying to use luv to build an NES emulator plugin that can communicate with another process without pausing the game emulation. I had something that was working smoothly when I tested it by manually typing in input data, but when I went to test communicating with another process via a pipe, the lua script never seemed to receive any data.

As a minimal reproducible example, use the following lua script:

local uv = require("luv")
local stdin = uv.new_poll(1)
stdin:start("r", function() print("uv callback") end)
uv.run("once")

When I press enter manually, everything works as expected:

% lua-5.1 min.lua
    
uv callback
%

However, passing in a blank line from another program via a pipe does not appear to work:

% echo | lua-5.1 min.lua
-- nothing happens, and lua-5.1 does not exit

I believe from additional testing that this is not a buffering issue: writing a program that manually flushes to put in place of echo and adding io.stdin:setvbuf("no") at the top of the lua script does not change the behavior. (In fact, experimentally it seems to somehow have attached directly to the terminal: pressing enter manually still causes the callback to run and the program to exit!)

Why doesn't my script see the piped-in data, and how can I change it so that it does?


Solution

  • Standard input is FD 0, not FD 1, so do uv.new_poll(0) instead of uv.new_poll(1). The reason it worked when you pressed Enter manually instead of piping into it is that with no pipes, all of the standard FDs are the TTY opened in read-write mode.