Creating LUA_FILEHANDLES is causing seg faults

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Creating LUA_FILEHANDLES is causing seg faults

Sean Conner

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)

(that first number is the process ID of the test code).  Here's the stack
dump:

(gdb) run luafilehandle.lua
Starting program: /home/spc/work/ecid/tests/bin/lua luafilehandle.lua
2013
about to create

file (0xa0b2058)        file (0xa0b28c8)
about to close read


Program received signal SIGSEGV, Segmentation fault.
0x00000000 in ?? ()
(gdb) where
#0  0x00000000 in ?? ()
#1  0x08063e5c in aux_close (L=0xa052008) at third_party/lua-5.1.4/src/liolib.c:130
#2  0x08063eaa in io_close (L=0xa052008) at third_party/lua-5.1.4/src/liolib.c:138
#3  0x080500f6 in luaD_precall (L=0xa052008, func=0xa05c490, nresults=-1) at third_party/lua-5.1.4/src/ldo.c:319
#4  0x0805bb11 in luaV_execute (L=0xa052008, nexeccalls=1) at third_party/lua-5.1.4/src/lvm.c:591
#5  0x0805030c in luaD_call (L=0xa052008, func=0xa052260, nResults=-1) at third_party/lua-5.1.4/src/ldo.c:377
#6  0x0804d57d in f_call (L=0xa052008, ud=0xbfebade0) at third_party/lua-5.1.4/src/lapi.c:800
#7  0x0804f6ff in luaD_rawrunprotected (L=0xa052008, f=0x804d55b <f_call>, ud=0xbfebade0) at third_party/lua-5.1.4/src/ldo.c:116
#8  0x0805062d in luaD_pcall (L=0xa052008, func=0x804d55b <f_call>, u=0xbfebade0, old_top=48, ef=36) at third_party/lua-5.1.4/src/ldo.c:463
#9  0x0804d5fd in lua_pcall (L=0xa052008, nargs=0, nresults=-1, errfunc=2) at third_party/lua-5.1.4/src/lapi.c:821
#10 0x0804aff6 in docall (L=0xa052008, narg=0, clear=0) at third_party/lua-5.1.4/src/lua.c:102
#11 0x0804b752 in handle_script (L=0xa052008, argv=0xbfebb154, n=1) at third_party/lua-5.1.4/src/lua.c:250
#12 0x0804bc22 in pmain (L=0xa052008) at third_party/lua-5.1.4/src/lua.c:362
#13 0x080500f6 in luaD_precall (L=0xa052008, func=0xa05223c, nresults=0) at third_party/lua-5.1.4/src/ldo.c:319
#14 0x080502f8 in luaD_call (L=0xa052008, func=0xa05223c, nResults=0) at third_party/lua-5.1.4/src/ldo.c:376
#15 0x0804d6c2 in f_Ccall (L=0xa052008, ud=0xbfebb060) at third_party/lua-5.1.4/src/lapi.c:846
#16 0x0804f6ff in luaD_rawrunprotected (L=0xa052008, f=0x804d62e <f_Ccall>, ud=0xbfebb060) at third_party/lua-5.1.4/src/ldo.c:116
#17 0x0805062d in luaD_pcall (L=0xa052008, func=0x804d62e <f_Ccall>, u=0xbfebb060, old_top=12, ef=0) at third_party/lua-5.1.4/src/ldo.c:463
#18 0x0804d6fe in lua_cpcall (L=0xa052008, func=0x804bac2 <pmain>, ud=0xbfebb0a0) at third_party/lua-5.1.4/src/lapi.c:856
#19 0x0804bd0f in main (argc=2, argv=0xbfebb154) at third_party/lua-5.1.4/src/lua.c:387
(gdb)

(/home/spc/work/ecid/tests/bin/lua is Lua 5.1.5 with symbol information
intact that I use for projects at work, thus the weird directory names)

Is there something I should be doing?  Code below.

  -spc (FYI---org.conman.cc [3] uses a Lua wrapper for TCC [4][5])

[1] A Unix system call that creates two file descriptors, one for
        reading, one for writing.

[2] A Unix function that accepts a file descriptor and returns a FILE *.

[3] https://github.com/spc476/lua-conmanorg/blob/master/lua/cc.lua

[4] A C compiler as a library

[5] https://github.com/spc476/lua-conmanorg/blob/master/src/tcc.c

-- ************* [ 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()

Reply | Threaded
Open this post in threaded view
|

Re: Creating LUA_FILEHANDLES is causing seg faults

Sean Bolton-2
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()
>


Reply | Threaded
Open this post in threaded view
|

Re: Creating LUA_FILEHANDLES is causing seg faults

Sean Conner
It was thus said that the Great Sean Bolton once stated:

> 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,

  Yup.  That was it.  I was able to grab the environment from io.open() and
use that, and the problem was fixed.

  -spc