Browse Source

GC of files is tricky when Lua is being closed...

v5-2
Roberto Ierusalimschy 26 years ago
parent
commit
bf7f85d609
  1. 36
      liolib.c

36
liolib.c

@ -1,5 +1,5 @@
/* /*
** $Id: liolib.c,v 1.34 1999/03/11 18:59:19 roberto Exp roberto $ ** $Id: liolib.c,v 1.35 1999/03/16 20:07:54 roberto Exp roberto $
** Standard I/O (and system) library ** Standard I/O (and system) library
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -74,7 +74,7 @@ static int gettag (void) {
} }
static int ishandler (lua_Object f) { static int ishandle (lua_Object f) {
if (lua_isuserdata(f)) { if (lua_isuserdata(f)) {
int tag = gettag(); int tag = gettag();
if (lua_tag(f) == CLOSEDTAG(tag)) if (lua_tag(f) == CLOSEDTAG(tag))
@ -87,7 +87,7 @@ static int ishandler (lua_Object f) {
static FILE *getfilebyname (char *name) { static FILE *getfilebyname (char *name) {
lua_Object f = lua_getglobal(name); lua_Object f = lua_getglobal(name);
if (!ishandler(f)) if (!ishandle(f))
luaL_verror("global variable `%.50s' is not a file handle", name); luaL_verror("global variable `%.50s' is not a file handle", name);
return lua_getuserdata(f); return lua_getuserdata(f);
} }
@ -95,13 +95,13 @@ static FILE *getfilebyname (char *name) {
static FILE *getfile (int arg) { static FILE *getfile (int arg) {
lua_Object f = lua_getparam(arg); lua_Object f = lua_getparam(arg);
return (ishandler(f)) ? lua_getuserdata(f) : NULL; return (ishandle(f)) ? lua_getuserdata(f) : NULL;
} }
static FILE *getnonullfile (int arg) { static FILE *getnonullfile (int arg) {
FILE *f = getfile(arg); FILE *f = getfile(arg);
luaL_arg_check(f, arg, "invalid file handler"); luaL_arg_check(f, arg, "invalid file handle");
return f; return f;
} }
@ -117,11 +117,17 @@ static FILE *getfileparam (char *name, int *arg) {
} }
static void rawclose (FILE *f) {
if (f != stdin && f != stdout) {
if (pclose(f) == -1) fclose(f);
}
}
static void closefile (FILE *f) { static void closefile (FILE *f) {
if (f != stdin && f != stdout) { if (f != stdin && f != stdout) {
int tag = gettag(); int tag = gettag();
if (pclose(f) == -1) rawclose(f);
fclose(f);
lua_pushusertag(f, tag); lua_pushusertag(f, tag);
lua_settag(CLOSEDTAG(tag)); lua_settag(CLOSEDTAG(tag));
} }
@ -133,6 +139,16 @@ static void io_close (void) {
} }
static void gc_close (void) {
int tag = luaL_check_int(1);
lua_Object fh = lua_getparam(2);
FILE *f = lua_getuserdata(fh);
luaL_arg_check(lua_isuserdata(fh) && lua_tag(fh) == tag, 2,
"invalid file handle for GC");
rawclose(f);
}
static void io_open (void) { static void io_open (void) {
FILE *f = fopen(luaL_check_string(1), luaL_check_string(2)); FILE *f = fopen(luaL_check_string(1), luaL_check_string(2));
if (f) lua_pushusertag(f, gettag()); if (f) lua_pushusertag(f, gettag());
@ -364,7 +380,7 @@ static void io_seek (void) {
static void io_flush (void) { static void io_flush (void) {
FILE *f = getfile(1); FILE *f = getfile(1);
luaL_arg_check(f || lua_getparam(1) == LUA_NOOBJECT, 1, luaL_arg_check(f || lua_getparam(1) == LUA_NOOBJECT, 1,
"invalid file handler"); "invalid file handle");
pushresult(fflush(f) == 0); pushresult(fflush(f) == 0);
} }
@ -550,7 +566,9 @@ void lua_iolibopen (void) {
/* make sure stdin (with its tag) won't be collected */ /* make sure stdin (with its tag) won't be collected */
lua_pushusertag(stdin, iotag); lua_ref(1); lua_pushusertag(stdin, iotag); lua_ref(1);
/* close file when collected */ /* close file when collected */
lua_pushcfunction(io_close); lua_settagmethod(iotag, "gc"); lua_pushnumber(iotag);
lua_pushcclosure(gc_close, 1);
lua_settagmethod(iotag, "gc");
/* register lib functions */ /* register lib functions */
luaL_openlib(iolib, (sizeof(iolib)/sizeof(iolib[0]))); luaL_openlib(iolib, (sizeof(iolib)/sizeof(iolib[0])));
} }

Loading…
Cancel
Save