diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1999-03-26 10:48:26 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1999-03-26 10:48:26 -0300 |
| commit | bf7f85d609291023bcc53df862198f5877ca00d6 (patch) | |
| tree | 3c5726b671d684e09064bb0e1df6b289fdc3a213 | |
| parent | a775a2d81ac31ae211a9682a2a57c6ca95e11115 (diff) | |
| download | lua-bf7f85d609291023bcc53df862198f5877ca00d6.tar.gz lua-bf7f85d609291023bcc53df862198f5877ca00d6.tar.bz2 lua-bf7f85d609291023bcc53df862198f5877ca00d6.zip | |
GC of files is tricky when Lua is being closed...
| -rw-r--r-- | liolib.c | 36 |
1 files changed, 27 insertions, 9 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: liolib.c,v 1.34 1999/03/11 18:59:19 roberto Exp roberto $ | 2 | ** $Id: liolib.c,v 1.35 1999/03/16 20:07:54 roberto Exp roberto $ |
| 3 | ** Standard I/O (and system) library | 3 | ** Standard I/O (and system) library |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -74,7 +74,7 @@ static int gettag (void) { | |||
| 74 | } | 74 | } |
| 75 | 75 | ||
| 76 | 76 | ||
| 77 | static int ishandler (lua_Object f) { | 77 | static int ishandle (lua_Object f) { |
| 78 | if (lua_isuserdata(f)) { | 78 | if (lua_isuserdata(f)) { |
| 79 | int tag = gettag(); | 79 | int tag = gettag(); |
| 80 | if (lua_tag(f) == CLOSEDTAG(tag)) | 80 | if (lua_tag(f) == CLOSEDTAG(tag)) |
| @@ -87,7 +87,7 @@ static int ishandler (lua_Object f) { | |||
| 87 | 87 | ||
| 88 | static FILE *getfilebyname (char *name) { | 88 | static FILE *getfilebyname (char *name) { |
| 89 | lua_Object f = lua_getglobal(name); | 89 | lua_Object f = lua_getglobal(name); |
| 90 | if (!ishandler(f)) | 90 | if (!ishandle(f)) |
| 91 | luaL_verror("global variable `%.50s' is not a file handle", name); | 91 | luaL_verror("global variable `%.50s' is not a file handle", name); |
| 92 | return lua_getuserdata(f); | 92 | return lua_getuserdata(f); |
| 93 | } | 93 | } |
| @@ -95,13 +95,13 @@ static FILE *getfilebyname (char *name) { | |||
| 95 | 95 | ||
| 96 | static FILE *getfile (int arg) { | 96 | static FILE *getfile (int arg) { |
| 97 | lua_Object f = lua_getparam(arg); | 97 | lua_Object f = lua_getparam(arg); |
| 98 | return (ishandler(f)) ? lua_getuserdata(f) : NULL; | 98 | return (ishandle(f)) ? lua_getuserdata(f) : NULL; |
| 99 | } | 99 | } |
| 100 | 100 | ||
| 101 | 101 | ||
| 102 | static FILE *getnonullfile (int arg) { | 102 | static FILE *getnonullfile (int arg) { |
| 103 | FILE *f = getfile(arg); | 103 | FILE *f = getfile(arg); |
| 104 | luaL_arg_check(f, arg, "invalid file handler"); | 104 | luaL_arg_check(f, arg, "invalid file handle"); |
| 105 | return f; | 105 | return f; |
| 106 | } | 106 | } |
| 107 | 107 | ||
| @@ -117,11 +117,17 @@ static FILE *getfileparam (char *name, int *arg) { | |||
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | 119 | ||
| 120 | static void rawclose (FILE *f) { | ||
| 121 | if (f != stdin && f != stdout) { | ||
| 122 | if (pclose(f) == -1) fclose(f); | ||
| 123 | } | ||
| 124 | } | ||
| 125 | |||
| 126 | |||
| 120 | static void closefile (FILE *f) { | 127 | static void closefile (FILE *f) { |
| 121 | if (f != stdin && f != stdout) { | 128 | if (f != stdin && f != stdout) { |
| 122 | int tag = gettag(); | 129 | int tag = gettag(); |
| 123 | if (pclose(f) == -1) | 130 | rawclose(f); |
| 124 | fclose(f); | ||
| 125 | lua_pushusertag(f, tag); | 131 | lua_pushusertag(f, tag); |
| 126 | lua_settag(CLOSEDTAG(tag)); | 132 | lua_settag(CLOSEDTAG(tag)); |
| 127 | } | 133 | } |
| @@ -133,6 +139,16 @@ static void io_close (void) { | |||
| 133 | } | 139 | } |
| 134 | 140 | ||
| 135 | 141 | ||
| 142 | static void gc_close (void) { | ||
| 143 | int tag = luaL_check_int(1); | ||
| 144 | lua_Object fh = lua_getparam(2); | ||
| 145 | FILE *f = lua_getuserdata(fh); | ||
| 146 | luaL_arg_check(lua_isuserdata(fh) && lua_tag(fh) == tag, 2, | ||
| 147 | "invalid file handle for GC"); | ||
| 148 | rawclose(f); | ||
| 149 | } | ||
| 150 | |||
| 151 | |||
| 136 | static void io_open (void) { | 152 | static void io_open (void) { |
| 137 | FILE *f = fopen(luaL_check_string(1), luaL_check_string(2)); | 153 | FILE *f = fopen(luaL_check_string(1), luaL_check_string(2)); |
| 138 | if (f) lua_pushusertag(f, gettag()); | 154 | if (f) lua_pushusertag(f, gettag()); |
| @@ -364,7 +380,7 @@ static void io_seek (void) { | |||
| 364 | static void io_flush (void) { | 380 | static void io_flush (void) { |
| 365 | FILE *f = getfile(1); | 381 | FILE *f = getfile(1); |
| 366 | luaL_arg_check(f || lua_getparam(1) == LUA_NOOBJECT, 1, | 382 | luaL_arg_check(f || lua_getparam(1) == LUA_NOOBJECT, 1, |
| 367 | "invalid file handler"); | 383 | "invalid file handle"); |
| 368 | pushresult(fflush(f) == 0); | 384 | pushresult(fflush(f) == 0); |
| 369 | } | 385 | } |
| 370 | 386 | ||
| @@ -550,7 +566,9 @@ void lua_iolibopen (void) { | |||
| 550 | /* make sure stdin (with its tag) won't be collected */ | 566 | /* make sure stdin (with its tag) won't be collected */ |
| 551 | lua_pushusertag(stdin, iotag); lua_ref(1); | 567 | lua_pushusertag(stdin, iotag); lua_ref(1); |
| 552 | /* close file when collected */ | 568 | /* close file when collected */ |
| 553 | lua_pushcfunction(io_close); lua_settagmethod(iotag, "gc"); | 569 | lua_pushnumber(iotag); |
| 570 | lua_pushcclosure(gc_close, 1); | ||
| 571 | lua_settagmethod(iotag, "gc"); | ||
| 554 | /* register lib functions */ | 572 | /* register lib functions */ |
| 555 | luaL_openlib(iolib, (sizeof(iolib)/sizeof(iolib[0]))); | 573 | luaL_openlib(iolib, (sizeof(iolib)/sizeof(iolib[0]))); |
| 556 | } | 574 | } |
