[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Non-blocking read from sub-process?
- From: Sean Conner <sean@...>
- Date: Tue, 5 Apr 2016 22:31:12 -0400
It was thus said that the Great Dan Christian once stated:
> I want to run a sub-process that may or may-not generate output. How
> can I make sure I don't block trying to read it. I'm happy to use
> luaposix, but I'm trying not to use a big event framework like lua-ev
> (because I'm memory limited and also don't want to cross compile it).
>
> Something like:
>
> f = io.popen(unknown_command, "r")
>
> while im_doing_something_else:
> data = f:read()
> if data:
> print ("Subproc says: ", data)
>
> kill(sub_proc)
Okay, I looked into this. I wrote a simple program:
#!/usr/bin/env lua
local clock = require "org.conman.clock" -- [1]
local data = string.rep("a",72) .. "\n"
for i = 1 , 5 do
io.stdout:write(data)
io.stdout:flush()
clock.sleep(1)
end
Once I had that, I then wrote the following with luaposix:
local posix = require "posix"
local cnt = 0
local f = io.popen("./b.lua","r")
local fd = posix.fileno(f)
local fds = { [fd] = { events = { IN = true } } }
while true do
cnt = cnt + 1
local events = posix.poll(fds,0) -- a timeout of 0
if events > 0 then
if fds[fd].revents.IN then
local data = f:read("*l")
print(data)
print(cnt)
elseif fds[fd].revents.HUP then
f:close()
return
end
end
end
And the output:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
564
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
124517
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
247551
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
370648
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
494827
This shows that we were able to count up while waiting for more input from
the running program. And just because I was curious (because I have my own
POSIX layer [2]):
local fsys = require "org.conman.fsys"
local pollset = require "org.conman.pollset"
local files = pollset()
local cnt = 0
local f = io.popen("./b.lua","r")
-- -------------------------------------------------------
-- select for "r"ead and "h"angup events on the given file
-- descriptor
-- -------------------------------------------------------
files:insert(fsys.fileno(f),"rh")
while true do
cnt = cnt + 1
local events = files:events(0) -- a timeout of 0
for _,event in ipairs(events) do
if event.read then
local data = f:read("*l")
print(data)
print(cnt)
elseif event.hangup then
f:close()
return
end
end
end
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
1652
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
379286
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
758243
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
1137190
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
1515319
Hmmm ... seems like my implementation of posix.poll() [3][4] is more efficient
(higher numbers consistently).
-spc (Hope this helps some)
[1] My POSIX layer over the timing functions.
https://github.com/spc476/lua-conmanorg/blob/master/src/clock.c
[2] https://github.com/spc476/lua-conmanorg/
[3] https://github.com/spc476/lua-conmanorg/blob/master/src/pollset.c
[4] I think this is largly because it will use epoll() under Linux;
poll() otherwise, and epoll() has much lower overhead than poll.
Also, posix.poll() has to scan the given array each time, while my
implemetation you only need to add the file descriptors once,
regardless of the underlying implementation (select(), poll() or
epoll()).