[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: LUA_FILEHANDLE creation from a third-party lib
- From: DarkGod <darkgod@...>
- Date: Mon, 28 May 2007 11:55:13 +0200
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;
}
}