diff options
author | Christian Pointner <equinox@spreadspace.org> | 2010-11-23 00:39:30 +0000 |
---|---|---|
committer | Christian Pointner <equinox@spreadspace.org> | 2010-11-23 00:39:30 +0000 |
commit | 559f5f720a33bd8b69a712a0d829ddc321f5aefe (patch) | |
tree | dad26c4fb5803d8a8a8908ca3a0d1b4ab38e4c09 | |
parent | mainloop now handles all return codes for writer as well (diff) |
exec and waitpid work with lua table for each child
git-svn-id: https://svn.spreadspace.org/gcsd/trunk@56 ac14a137-c7f1-4531-abe0-07747231d213
-rw-r--r-- | src/l_util.c | 146 | ||||
-rw-r--r-- | src/main_loop.lua | 13 | ||||
-rw-r--r-- | src/modules/exec.lua | 14 |
3 files changed, 55 insertions, 118 deletions
diff --git a/src/l_util.c b/src/l_util.c index 9b87beb..41bfcdd 100644 --- a/src/l_util.c +++ b/src/l_util.c @@ -220,118 +220,48 @@ void free_ptrptr(char** ptrptr) free(ptrptr); } -struct child_struct { - pid_t pid_; - int fd_; - struct child_struct* next_; -}; -typedef struct child_struct child_t; - -child_t* child_get_last(child_t* first) -{ - if(!first) - return NULL; - - while(first->next_) { - first = first->next_; - } - return first; -} - -int child_add(lua_State *L, pid_t pid, int fd) -{ - lua_getglobal(L, LUA_UTILLIBNAME); - lua_getfield(L, -1, LUA_UTILCHLIDRENNAME); - child_t* first = lua_touserdata(L, -1); - lua_pop(L, 1); - - child_t* new_child = malloc(sizeof(child_t)); - if(!new_child) - return -1; - - new_child->pid_ = pid; - new_child->fd_ = fd; - new_child->next_ = NULL; - if(!first) { - lua_pushlightuserdata(L, new_child); - lua_setfield(L, -2, LUA_UTILCHLIDRENNAME); - lua_pop(L, 1); - return 0; - } - child_get_last(first)->next_ = new_child; - lua_pop(L, 1); - return 0; -} - -void child_remove(lua_State *L, pid_t pid) +static int child_add(lua_State *L, pid_t pid, int fd) { lua_getglobal(L, LUA_UTILLIBNAME); lua_getfield(L, -1, LUA_UTILCHLIDRENNAME); - child_t* first = lua_touserdata(L, -1); - if(!first) { - lua_pop(L, 2); - return; - } - lua_pop(L, 1); - - child_t* deletee = first; - if(first->pid_ == pid) { - lua_pushlightuserdata(L, first->next_); - lua_setfield(L, -2, LUA_UTILCHLIDRENNAME); - lua_pop(L, 1); - close(deletee->fd_); - free(deletee); - return; - } - lua_pop(L, 1); - child_t* prev = deletee; - deletee = deletee->next_; - while(deletee) { - if(deletee->pid_ == pid) { - prev->next_ = deletee->next_; - close(deletee->fd_); - free(deletee); - return; - } - prev = deletee; - deletee = deletee->next_; - } + lua_remove(L, -2); + lua_newtable(L); + lua_pushinteger(L, pid); + lua_setfield(L, -2, "pid"); + lua_pushinteger(L, fd); + lua_setfield(L, -2, "errfd"); + lua_pushinteger(L, pid); + lua_pushvalue(L, -2); + lua_settable(L, -4); + lua_remove(L, -2); } -child_t* child_find(lua_State *L, pid_t pid) +static void child_remove(lua_State *L, pid_t pid) { lua_getglobal(L, LUA_UTILLIBNAME); lua_getfield(L, -1, LUA_UTILCHLIDRENNAME); - child_t* first = lua_touserdata(L, -1); + lua_pushinteger(L, pid); + lua_pushnil(L); + lua_settable(L, -3); lua_pop(L, 2); - - if(!first) - return NULL; - - while(first) { - if(first->pid_ == pid) - return first; - - first = first->next_; - } - return NULL; } -void child_clear(lua_State *L, pid_t pid) +static int child_find(lua_State *L, pid_t pid) { lua_getglobal(L, LUA_UTILLIBNAME); lua_getfield(L, -1, LUA_UTILCHLIDRENNAME); - child_t* first = lua_touserdata(L, -1); - lua_pop(L, 1); - lua_pushlightuserdata(L, NULL); - lua_setfield(L, -2, LUA_UTILCHLIDRENNAME); - - while(first) { - child_t* tmp = first; - first = tmp->next_; - close(tmp->fd_); - free(tmp); + lua_pushinteger(L, pid); + lua_gettable(L, -2); + if(lua_isnil(L, -1)) { + lua_pop(L, 3); + return -1; } + lua_getfield(L, -1, "errfd"); + int fd = luaL_checkint(L, -1); + lua_pop(L, 1); + lua_remove(L, -2); + lua_remove(L, -3); + return fd; } static void prepare_fds(lua_State *L, int *child_stdio, int pipefd) @@ -400,8 +330,6 @@ static int l_util_exec(lua_State *L) } close(pipefd[1]); child_add(L, pid, pipefd[0]); - - lua_pushinteger(L, pid); return 1; } @@ -410,7 +338,7 @@ static int l_util_waitpid(lua_State *L) int status = 0; pid_t pid = waitpid(-1, &status, WNOHANG); if(!pid || (pid < 0 && (errno == ECHILD))) { - lua_pushinteger(L, 0); + lua_pushnil(L); return 1; } if(pid < 0) { @@ -419,17 +347,21 @@ static int l_util_waitpid(lua_State *L) return 2; } - lua_pushinteger(L, pid); - child_t* child = child_find(L, pid); - if(child) { + int errfd = child_find(L, pid); + if(errfd != -1) { + child_remove(L, pid); int err = 0; - if(read(child->fd_, (void*)(&err), sizeof(err)) >= sizeof(err)) { + if(read(errfd, (void*)(&err), sizeof(err)) >= sizeof(err)) { lua_pushliteral(L, "error"); lua_pushstring(L, strerror(err)); // FIXXXXXME: strerror is not threadsafe!!! - child_remove(L, pid); + close(errfd); return 3; } - child_remove(L, pid); + close(errfd); + } else { + lua_pushnil(L); + lua_pushliteral(L, "unknown child pid returned"); + return 2; } if(WIFEXITED(status)) { lua_pushliteral(L, "exit"); @@ -531,7 +463,7 @@ static const struct luaL_reg util_funcs [] = { LUALIB_API int luaopen_util(lua_State *L) { luaL_register(L, LUA_UTILLIBNAME, util_funcs); - lua_pushlightuserdata(L, NULL); + lua_newtable(L); lua_setfield(L, -2, LUA_UTILCHLIDRENNAME); return 1; } diff --git a/src/main_loop.lua b/src/main_loop.lua index 3211660..22809aa 100644 --- a/src/main_loop.lua +++ b/src/main_loop.lua @@ -85,11 +85,14 @@ function main_loop(opt) local readable, writeable, err = util.select({ sig, unpack(get_readables()) }, get_writeables(), 10) if(err) then if(err == "timeout") then - local pid, reason, status = util.waitpid() - if(pid == nil) then - log.printf(log.DEBUG, "waitpid failed: " .. reason) - elseif(pid > 0) then - log.printf(log.DEBUG, "child with pid %d stopped, reason: %s, code: %s", pid, reason, tostring(status)) + local child, reason, status = util.waitpid() + if(child == nil) then + if(reason ~= nil) then + log.printf(log.DEBUG, "waitpid failed: " .. reason) + end + else + log.printf(log.DEBUG, "child with pid %d stopped, reason: %s, code: %s", child.pid, reason, tostring(status)) + if(child.cleanup ~= nil) then child:cleanup() end end elseif(err == "signal") then -- ignore this diff --git a/src/modules/exec.lua b/src/modules/exec.lua index 765fdb6..239248f 100644 --- a/src/modules/exec.lua +++ b/src/modules/exec.lua @@ -36,6 +36,7 @@ local defines = require("defines") local exec = {} exec.properties = { type=defines.INOUT_MODULE, name="exec", max_instances=-1 } exec.defaults = { script = "exec.sh" } +exec.next_id = 0 -- create new instance of exec module class function exec:new(config) @@ -43,7 +44,8 @@ function exec:new(config) inst.class = self.properties.name inst.config = config if(config.name == nil or config.name == "") then - inst.name = self.properties.name + inst.name = self.properties.name .. self.next_id + self.next_id = self.next_id + 1 else inst.name = config.name end @@ -59,13 +61,13 @@ function exec:new(config) log.printf(log.ERROR, inst.name .. ": pipe failed: %s", reader_child) return nil end - local pid, err = util.exec(config.script, nil, nil, reader_child, writer_child) - if(pid == nil) then + local child, err = util.exec(config.script, nil, nil, reader_child, writer_child) + if(child == nil) then log.printf(log.ERROR, inst.name .. ": exec failed: %s", error) return nil end - log.printf(log.NOTICE, inst.name .. ": child spawned with pid %d", pid) + log.printf(log.NOTICE, inst.name .. ": child spawned with pid %d", child.pid) local in_handle = {} in_handle.fd = reader @@ -114,7 +116,7 @@ function exec:new(config) local client = {} client.module_instance = inst client.name = inst.name .. "#0" - client.pid = pid + client.pid = child.pid function client:process_response() end function client:process_timeout() end function client:get_read_handles() @@ -128,7 +130,7 @@ function exec:new(config) end end function client:cleanup() - util.kill(pid) + util.kill(self.pid) end in_handle.client_instance = client out_handle.client_instance = client |