lua-users home
lua-l archive

LUA_FILEHANDLE creation from a third-party lib

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Hullo all,
I've made myself a small C module for Lua that allows to call an external program while capturing both the input and output streams (using the classic combinaison of fork/exec/dup2) and to ask if
a file handle is readable/writable and to bind the "wait" system call.
Now when I do that(see code below) it works all fine except when one of my file handles needs to
be garbage collected I get a nasty segfault.
But if I put my code into lua's liolib.c (registering it in luaL_Reg iolib[]) and compile it, it works just fine. The crash happens in liolib.c:aux_close():120, seemingly missing the "__close" field. I'm creating my handle the same way iolib does, assigning the metatable, so there must be something very
basic and stupid I'm forgetting right?
Thanks for your help
Relevant code:
static FILE **newfile_fd(lua_State *L, int fd, const char *mode)
{
 FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *));
 *pf = NULL; /* file handle is currently `closed' */
 luaL_getmetatable(L, LUA_FILEHANDLE);
 lua_setmetatable(L, -2);
 *pf = fdopen(fd, mode);
 return pf;
}
static int lpc_run(lua_State *L)
{
 int p_out[2];
 int p_in[2];
 int pid;
 if (pipe(p_out) == -1) { lua_pushnil(L); return 1; }
 if (pipe(p_in) == -1) { lua_pushnil(L); return 1; }
 if ((pid = fork()) == -1) { lua_pushnil(L); return 1; }
 else if (pid == 0)
 {
 char **args;
 int n = lua_gettop(L); /* number of arguments */
 int i;
 args = luaM_malloc(L, (n + 1) * sizeof(char*));
 for (i = 1; i <= n; i++)
 {
 args[i - 1] = (char*)luaL_checkstring(L, i);
 }
 args[n] = NULL;
 close(p_out[1]);
 close(p_in[0]);
 dup2(p_out[0], 0);
 dup2(p_in[1], 1);
 close(p_out[0]);
 close(p_in[1]);
 execvp(args[0], args);
 perror("LPC child error");
 _exit(1);
 return 0;
 }
 else
 {
 FILE **in;
 FILE **out;
 /* Cleanup */
 close(p_out[0]);
 close(p_in[1]);
 lua_pushnumber(L, pid);
 out = newfile_fd(L, p_out[1], "w");
 in = newfile_fd(L, p_in[0], "r");
 return 3;
 }
}

AltStyle によって変換されたページ (->オリジナル) /