waitpid() failed (10: No child processes)

1,281 views
Skip to first unread message

Ivan Ribeiro

unread,
Dec 3, 2013, 5:25:04 PM12/3/13
to openre...@googlegroups.com
Hi,

   Please, I need something similar to os.execute or io.popen to call a program from my lua script and check the result status or the stdout. When I use both, I get a message like this:

   2013/12/03 20:10:14 [info] 8239#0: waitpid() failed (10: No child processes)

   What is the best way to handle this situation?

   Thanks in advance,

       Ivan

Yichun Zhang (agentzh)

unread,
Dec 3, 2013, 5:51:44 PM12/3/13
to openresty-en
Hello!

On Tue, Dec 3, 2013 at 2:25 PM, Ivan Ribeiro wrote:
> Please, I need something similar to os.execute or io.popen to call a
> program from my lua script and check the result status or the stdout. When I
> use both, I get a message like this:
>
> 2013/12/03 20:10:14 [info] 8239#0: waitpid() failed (10: No child
> processes)
>

In short: don't do that.

os.execute and io.popen will both block your nginx worker processes
(possibly for long), which will kill the overall performance.

That info message itself is usually harmless because os.execute and
io.popen both spawn new child processes. We can reduce the number of
this messages by explicitly calling close() as soon as possible in
your Lua code for the file returned by io.popen().

I have a plan of implementing a nonblocking pipe API in ngx_lua to
replace io.popen() and the alike. We'll still have to clone a new
child process anyway which is not C10K capable, but it will not block
the nginx workers at least. Patches welcome ;)

Best regards,
-agentzh

anton....@cbsinteractive.com

unread,
Mar 31, 2014, 1:01:25 PM3/31/14
to openre...@googlegroups.com
If your host system is Linux/Unix-like, then you could run a helper 
daemon process, which listens locally on a unix socket and spawns 
a child process to execute the shell command that you provide. 
I needed this for one of my projects, so i wrote a simple implementation of it:


Seems to work pretty well. Your shell module in Lua then becomes very simple: 
it uses co-socket API to talk to the sockproc daemon, and therefore is 
completely non-blocking:


-- Non-blocking replacement for os.execute

local shell = {}
local sockproc_socket = "unix:/tmp/hello.sock"

function shell.execute(cmd, args)
    local timeout = args and args.timeout
    local input_data = args and args.data or ""
    local sock = ngx.socket.tcp()
    local ok, err = sock:connect(sockproc_socket)
    if ok then
        sock:settimeout(timeout or 15000)
        sock:send(cmd .. "\r\n")
        sock:send(string.format("%d\r\n", #input_data))
        sock:send(input_data)

        -- status code
        local data, err, partial = sock:receive('*l')
        if err then
            return -1, nil, err
        end
        local code = string.match(data,"status:([-%d]+)") or -1
        -- output stream
        data, err, partial = sock:receive('*l')
        if err then
            return -1, nil, err
        end
        local n = tonumber(data) or 0
        local out_bytes = n > 0 and sock:receive(n) or nil
        -- error stream
        data, err, partial = sock:receive('*l')
        if err then
            return -1, nil, err
        end
        n = tonumber(data) or 0
        local err_bytes = n > 0 and sock:receive(n) or nil
        sock:close()

        return tonumber(code), out_bytes, err_bytes
    end
    return -2, nil, err
end

return shell

Anton Jouline

unread,
Mar 31, 2014, 5:53:07 PM3/31/14
to openre...@googlegroups.com
I put the shell module into github too, in case anyone wants it. Feel free to use, fork, whatever :)



Anton.
Reply all
Reply to author
Forward
0 new messages