summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Pointner <equinox@spreadspace.org>2010-11-22 01:29:23 +0000
committerChristian Pointner <equinox@spreadspace.org>2010-11-22 01:29:23 +0000
commita02695a4c39ebbea948dd52eb8ee184174011f3b (patch)
treecaeea81bd4c25e7a3cd4d3c3bb05b1f35830519b /src
parentenvironment pointer works now at exec (diff)
added error pipe in case execve returns - not working yet..
git-svn-id: https://svn.spreadspace.org/gcsd/trunk@47 ac14a137-c7f1-4531-abe0-07747231d213
Diffstat (limited to 'src')
-rw-r--r--src/l_util.c132
-rw-r--r--src/l_util.h1
2 files changed, 131 insertions, 2 deletions
diff --git a/src/l_util.c b/src/l_util.c
index 0b417ac..6ef6236 100644
--- a/src/l_util.c
+++ b/src/l_util.c
@@ -219,6 +219,103 @@ 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)
+{
+ 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_;
+ }
+}
+
+child_t* 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, 2);
+
+ if(!first)
+ return NULL;
+
+ while(first) {
+ if(first->pid_ == pid)
+ return first;
+
+ first = first->next_;
+ }
+ return NULL;
+}
+
static int l_util_exec(lua_State *L)
{
const char* script = luaL_checkstring(L, 1);
@@ -231,10 +328,17 @@ static int l_util_exec(lua_State *L)
return 2;
}
+ int pipefd[2];
+ if(pipe(pipefd) == -1) {
+ lua_pushnil(L);
+ lua_pushstring(L, strerror(errno)); // FIXXXXXME: strerror is not threadsafe!!!
+ return 2;
+ }
+
if(!pid) {
int fd;
for (fd=getdtablesize();fd>=0;--fd) // close all file descriptors
- close(fd);
+ if(fd != pipefd[1]) close(fd);
char** argv = table_to_argv(L, script, 2);
char** evp = table_to_evp(L, 3);
@@ -245,11 +349,17 @@ static int l_util_exec(lua_State *L)
}
execve(script, argv, evp);
+ // if execve returns, an error occurred, but logging doesn't work
+ // because we closed all file descriptors, so just write errno to
+ // pipe and call exit
+ int ret = write(pipefd[1], (void*)(&errno), sizeof(errno));
free_ptrptr(argv);
free_ptrptr(evp);
lua_close(L);
- exit(-1);
+ exit(ret);
}
+ close(pipefd[1]);
+ child_add(L, pid, pipefd[0]);
lua_pushinteger(L, pid);
return 1;
@@ -270,6 +380,22 @@ static int l_util_waitpid(lua_State *L)
}
lua_pushinteger(L, pid);
+ child_t* child = child_find(L, pid);
+ if(child) {
+ fd_set rfds;
+ FD_ZERO(&rfds);
+ FD_SET(child->fd_, &rfds);
+ struct timeval tv = { 0 , 0 };
+ if(select(child->fd_+1, &rfds, NULL, NULL, &tv) == 1) {
+ int err = 0;
+ if(read(child->fd_, (void*)(&err), sizeof(err)) >= sizeof(err)) {
+ lua_pushliteral(L, "error");
+ lua_pushstring(L, strerror(errno)); // FIXXXXXME: strerror is not threadsafe!!!
+ return 3;
+ }
+ }
+ child_remove(L, pid);
+ }
if(WIFEXITED(status)) {
lua_pushliteral(L, "exit");
lua_pushinteger(L, WEXITSTATUS(status));
@@ -309,5 +435,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_setfield(L, -2, LUA_UTILCHLIDRENNAME);
return 1;
}
diff --git a/src/l_util.h b/src/l_util.h
index c0b558a..14422b8 100644
--- a/src/l_util.h
+++ b/src/l_util.h
@@ -36,6 +36,7 @@
#include <lua.h>
#define LUA_UTILLIBNAME "util"
+#define LUA_UTILCHLIDRENNAME "__children"
LUALIB_API int luaopen_util(lua_State *L);
#endif