lua-users home
lua-l archive

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


Hi Sean,

On Fri May 10 2013, Sean Conner wrote:
> I wrote a function that calls pipe() [1].  Once that succeeds, I call
> fdopen() [2] on each file descriptor, and then I create
> LUA_FILEHANDLES from these and return both of them (in a table).  The
> create portion is fine, but when I try to close one of the pipes:
> 
> [spc]lucy:/tmp>lua luafilehandle.lua 
> 2011
> about to create
> 
> file (0x96647e8)        file (0x967b148)
> about to close read
> 
> Segmentation fault (core dumped)

[snip]

> Is there something I should be doing?  Code below.

Yes, you're not setting the environment of the file handle userdata, or
better yet, of my_pipe() (so that all userdata created by it inherit
the correct environment). It's from the file handle object's environment
that Lua 5.1.x gets the function to use to close the handle. Since your
userdata don't have that set, the close crashes.  Grep for 'fenv' in
liolib.c for more information.  (Note that 5.2 uses a different
scheme.) HTH,

-Sean

> -- ************* [ Code starts here ] **********************
> 
> cc = require "org.conman.cc"
> 
> getpid = cc.compile("my_getpid",[[
> #include <unistd.h>
> #include <lua.h>
> 
> int my_getpid(lua_State *L)
> {
>   lua_pushnumber(L,getpid());
>   return 1;
> }
> ]])
> 
> pipe = cc.compile("my_pipe",[[
> #include <stdio.h>
> #include <errno.h>
> #include <unistd.h>
> #include <lua.h>
> #include <lauxlib.h>
> #include <lualib.h>
> 
> int my_pipe(lua_State *L)
> {
>   FILE **pfpread;
>   FILE **pfpwrite;
>   FILE  *fpr;
>   FILE  *fpw;
>   int    fh[2];
>   char  *rm;
>   char  *wm;
>   
>   if (lua_isboolean(L,1))
>   {
>     rm = "rb";
>     wm = "wb";
>   }
>   else
>   {
>     rm = "r";
>     wm = "w";
>   }
>   
>   if (pipe(fh) < 0)
>   {
>     lua_pushnil(L);
>     lua_pushinteger(L,errno);
>     return 2;
>   }
>   
>   fpr = fdopen(fh[0],rm);
>   if (fpr == NULL)
>   {
>     lua_pushnil(L);
>     lua_pushinteger(L,errno);
>     close(fh[0]);
>     close(fh[1]);
>     return 2;
>   }
>   
>   fpw = fdopen(fh[1],wm);
>   if (fpw == NULL)
>   {
>     lua_pushnil(L);
>     lua_pushinteger(L,errno);
>     fclose(fpr);
>     close(fh[1]);
>     return 2;
>   }
>   
>   lua_createtable(L,0,2);
>   
>   pfpread  = lua_newuserdata(L,sizeof(FILE *));
>   *pfpread = fpr;
>   luaL_getmetatable(L,LUA_FILEHANDLE);
>   lua_setmetatable(L,-2);
>   lua_setfield(L,-2,"read");
>   
>   pfpwrite  = lua_newuserdata(L,sizeof(FILE *));
>   *pfpwrite = fpw;
>   luaL_getmetatable(L,LUA_FILEHANDLE);
>   lua_setmetatable(L,-2);
>   lua_setfield(L,-2,"write");
>   
>   lua_pushinteger(L,0);
>   return 2;
> }
> ]])
> 
> print(getpid())
> 
> print("about to create") io.stdin:read()
> x = pipe()
> print(x.read,x.write)
> print("about to close read") io.stdin:read()
> print(x.read:close())
> print("about to close write") io.stdin:read()
> print(x.write:close())
> print("about to exit") io.stdin:read()
>