# HG changeset patch # User jbe # Date 1510756542 -3600 # Node ID 477456cea3610ea1a9f2fc5db24eb6e300f43b51 # Parent b2282fb8553bb14a598915c7ee8031d8efd197c4 Avoid using WNOWAIT in moonbridge_io.poll(...) for Linux compatibility diff -r b2282fb8553b -r 477456cea361 moonbridge_io.c --- a/moonbridge_io.c Fri Jun 23 15:49:43 2017 +0200 +++ b/moonbridge_io.c Wed Nov 15 15:35:42 2017 +0100 @@ -114,6 +114,8 @@ typedef struct { pid_t pid; + int status; + int status_valid; } moonbr_io_child_t; volatile sig_atomic_t moonbr_io_sigterm_flag = 0; @@ -1367,6 +1369,7 @@ argv[argc] = NULL; child = lua_newuserdata(L, sizeof(moonbr_io_child_t)); child->pid = 0; + child->status_valid = 0; lua_newtable(L); lua_setuservalue(L, -2); luaL_setmetatable(L, MOONBR_IO_CHILD_MT_REGKEY); @@ -1535,10 +1538,13 @@ int sig; child = luaL_checkudata(L, 1, MOONBR_IO_CHILD_MT_REGKEY); sig = luaL_optinteger(L, 2, SIGKILL); - if (!child->pid) luaL_error(L, "Attempt to kill an already collected child process"); - if (kill(child->pid, sig)) { - moonbr_io_prepare_errmsg(); - luaL_error(L, "Error in kill call: %s", errmsg); + if (!child->pid) { + if (!child->status_valid) luaL_error(L, "Attempt to kill an already collected child process"); + } else { + if (kill(child->pid, sig)) { + moonbr_io_prepare_errmsg(); + luaL_error(L, "Error in kill call: %s", errmsg); + } } lua_settop(L, 1); return 1; @@ -1546,31 +1552,35 @@ static int moonbr_io_wait_impl(lua_State *L, int nonblocking) { moonbr_io_child_t *child; - pid_t waitedpid; int status; child = luaL_checkudata(L, 1, MOONBR_IO_CHILD_MT_REGKEY); - if (!child->pid) luaL_error(L, "Attempt to wait for an already collected child process"); - while ((waitedpid = waitpid(child->pid, &status, nonblocking ? WNOHANG : 0)) == -1) { - if (errno != EINTR) { - moonbr_io_prepare_errmsg(); - luaL_error(L, "Error in waitpid call: %s", errmsg); + if (!child->pid) { + if (!child->status_valid) luaL_error(L, "Attempt to wait for an already collected child process"); + status = child->status; + child->status_valid = 0; + } else { + pid_t waitedpid; + while ((waitedpid = waitpid(child->pid, &status, nonblocking ? WNOHANG : 0)) == -1) { + if (errno != EINTR) { + moonbr_io_prepare_errmsg(); + luaL_error(L, "Error in waitpid call: %s", errmsg); + } } + if (!waitedpid) { + lua_pushboolean(L, 0); + lua_pushliteral(L, "Process is still running"); + return 2; + } + child->pid = 0; } - if (!waitedpid) { - lua_pushboolean(L, 0); - lua_pushliteral(L, "Process is still running"); - return 2; + if (WIFEXITED(status)) { + lua_pushinteger(L, WEXITSTATUS(status)); + } else if (WIFSIGNALED(status)) { + lua_pushinteger(L, -WTERMSIG(status)); } else { - child->pid = 0; - if (WIFEXITED(status)) { - lua_pushinteger(L, WEXITSTATUS(status)); - } else if (WIFSIGNALED(status)) { - lua_pushinteger(L, -WTERMSIG(status)); - } else { - luaL_error(L, "Unexpected status value returned by waitpid call"); - } - return 1; + luaL_error(L, "Unexpected status value returned by waitpid call"); } + return 1; } static int moonbr_io_wait(lua_State *L) { @@ -1709,13 +1719,22 @@ moonbr_io_sigchld_flag = 0; signal(SIGCHLD, moonbr_io_sigchld_handler); } - while ((waitedpid = waitpid(child->pid, &status, WNOHANG|WNOWAIT)) == -1) { - if (errno != EINTR) { - moonbr_io_prepare_errmsg(); - luaL_error(L, "Error in waitpid call: %s", errmsg); + if (child->status_valid) { + force_wakeup = 1; + } else { + while ((waitedpid = waitpid(child->pid, &status, WNOHANG)) == -1) { + if (errno != EINTR) { + moonbr_io_prepare_errmsg(); + luaL_error(L, "Error in waitpid call: %s", errmsg); + } + } + if (waitedpid) { + child->pid = 0; + child->status = status; + child->status_valid = 1; + force_wakeup = 1; } } - if (waitedpid) force_wakeup = 1; continue; } else { fd = lua_tointegerx(L, -2, &isnum);