summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Pointner <equinox@spreadspace.org>2010-11-23 00:39:30 +0000
committerChristian Pointner <equinox@spreadspace.org>2010-11-23 00:39:30 +0000
commit559f5f720a33bd8b69a712a0d829ddc321f5aefe (patch)
treedad26c4fb5803d8a8a8908ca3a0d1b4ab38e4c09
parentmainloop 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.c146
-rw-r--r--src/main_loop.lua13
-rw-r--r--src/modules/exec.lua14
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