moonbridge
changeset 303:477456cea361
Avoid using WNOWAIT in moonbridge_io.poll(...) for Linux compatibility
author | jbe |
---|---|
date | Wed Nov 15 15:35:42 2017 +0100 (2017-11-15) |
parents | b2282fb8553b |
children | e18589f22314 |
files | moonbridge_io.c |
line diff
1.1 --- a/moonbridge_io.c Fri Jun 23 15:49:43 2017 +0200 1.2 +++ b/moonbridge_io.c Wed Nov 15 15:35:42 2017 +0100 1.3 @@ -114,6 +114,8 @@ 1.4 1.5 typedef struct { 1.6 pid_t pid; 1.7 + int status; 1.8 + int status_valid; 1.9 } moonbr_io_child_t; 1.10 1.11 volatile sig_atomic_t moonbr_io_sigterm_flag = 0; 1.12 @@ -1367,6 +1369,7 @@ 1.13 argv[argc] = NULL; 1.14 child = lua_newuserdata(L, sizeof(moonbr_io_child_t)); 1.15 child->pid = 0; 1.16 + child->status_valid = 0; 1.17 lua_newtable(L); 1.18 lua_setuservalue(L, -2); 1.19 luaL_setmetatable(L, MOONBR_IO_CHILD_MT_REGKEY); 1.20 @@ -1535,10 +1538,13 @@ 1.21 int sig; 1.22 child = luaL_checkudata(L, 1, MOONBR_IO_CHILD_MT_REGKEY); 1.23 sig = luaL_optinteger(L, 2, SIGKILL); 1.24 - if (!child->pid) luaL_error(L, "Attempt to kill an already collected child process"); 1.25 - if (kill(child->pid, sig)) { 1.26 - moonbr_io_prepare_errmsg(); 1.27 - luaL_error(L, "Error in kill call: %s", errmsg); 1.28 + if (!child->pid) { 1.29 + if (!child->status_valid) luaL_error(L, "Attempt to kill an already collected child process"); 1.30 + } else { 1.31 + if (kill(child->pid, sig)) { 1.32 + moonbr_io_prepare_errmsg(); 1.33 + luaL_error(L, "Error in kill call: %s", errmsg); 1.34 + } 1.35 } 1.36 lua_settop(L, 1); 1.37 return 1; 1.38 @@ -1546,31 +1552,35 @@ 1.39 1.40 static int moonbr_io_wait_impl(lua_State *L, int nonblocking) { 1.41 moonbr_io_child_t *child; 1.42 - pid_t waitedpid; 1.43 int status; 1.44 child = luaL_checkudata(L, 1, MOONBR_IO_CHILD_MT_REGKEY); 1.45 - if (!child->pid) luaL_error(L, "Attempt to wait for an already collected child process"); 1.46 - while ((waitedpid = waitpid(child->pid, &status, nonblocking ? WNOHANG : 0)) == -1) { 1.47 - if (errno != EINTR) { 1.48 - moonbr_io_prepare_errmsg(); 1.49 - luaL_error(L, "Error in waitpid call: %s", errmsg); 1.50 + if (!child->pid) { 1.51 + if (!child->status_valid) luaL_error(L, "Attempt to wait for an already collected child process"); 1.52 + status = child->status; 1.53 + child->status_valid = 0; 1.54 + } else { 1.55 + pid_t waitedpid; 1.56 + while ((waitedpid = waitpid(child->pid, &status, nonblocking ? WNOHANG : 0)) == -1) { 1.57 + if (errno != EINTR) { 1.58 + moonbr_io_prepare_errmsg(); 1.59 + luaL_error(L, "Error in waitpid call: %s", errmsg); 1.60 + } 1.61 } 1.62 + if (!waitedpid) { 1.63 + lua_pushboolean(L, 0); 1.64 + lua_pushliteral(L, "Process is still running"); 1.65 + return 2; 1.66 + } 1.67 + child->pid = 0; 1.68 } 1.69 - if (!waitedpid) { 1.70 - lua_pushboolean(L, 0); 1.71 - lua_pushliteral(L, "Process is still running"); 1.72 - return 2; 1.73 + if (WIFEXITED(status)) { 1.74 + lua_pushinteger(L, WEXITSTATUS(status)); 1.75 + } else if (WIFSIGNALED(status)) { 1.76 + lua_pushinteger(L, -WTERMSIG(status)); 1.77 } else { 1.78 - child->pid = 0; 1.79 - if (WIFEXITED(status)) { 1.80 - lua_pushinteger(L, WEXITSTATUS(status)); 1.81 - } else if (WIFSIGNALED(status)) { 1.82 - lua_pushinteger(L, -WTERMSIG(status)); 1.83 - } else { 1.84 - luaL_error(L, "Unexpected status value returned by waitpid call"); 1.85 - } 1.86 - return 1; 1.87 + luaL_error(L, "Unexpected status value returned by waitpid call"); 1.88 } 1.89 + return 1; 1.90 } 1.91 1.92 static int moonbr_io_wait(lua_State *L) { 1.93 @@ -1709,13 +1719,22 @@ 1.94 moonbr_io_sigchld_flag = 0; 1.95 signal(SIGCHLD, moonbr_io_sigchld_handler); 1.96 } 1.97 - while ((waitedpid = waitpid(child->pid, &status, WNOHANG|WNOWAIT)) == -1) { 1.98 - if (errno != EINTR) { 1.99 - moonbr_io_prepare_errmsg(); 1.100 - luaL_error(L, "Error in waitpid call: %s", errmsg); 1.101 + if (child->status_valid) { 1.102 + force_wakeup = 1; 1.103 + } else { 1.104 + while ((waitedpid = waitpid(child->pid, &status, WNOHANG)) == -1) { 1.105 + if (errno != EINTR) { 1.106 + moonbr_io_prepare_errmsg(); 1.107 + luaL_error(L, "Error in waitpid call: %s", errmsg); 1.108 + } 1.109 + } 1.110 + if (waitedpid) { 1.111 + child->pid = 0; 1.112 + child->status = status; 1.113 + child->status_valid = 1; 1.114 + force_wakeup = 1; 1.115 } 1.116 } 1.117 - if (waitedpid) force_wakeup = 1; 1.118 continue; 1.119 } else { 1.120 fd = lua_tointegerx(L, -2, &isnum);