aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-07-27 15:50:53 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-07-27 15:50:53 -0300
commit3d838f635cc81ec3332f9a904992db1c6d8a46ad (patch)
treefe2e9aa951d3e0dd464481697d4fb671bde70e65
parentaa4c5cf190f77ab2730af5e21cfd2b830ff329df (diff)
downloadlua-3d838f635cc81ec3332f9a904992db1c6d8a46ad.tar.gz
lua-3d838f635cc81ec3332f9a904992db1c6d8a46ad.tar.bz2
lua-3d838f635cc81ec3332f9a904992db1c6d8a46ad.zip
Added "emergency collection" to 'io.tmpfile' and 'os.tmpname'
These operations also can give errors for lack of resources, so they also will try "emergency collections" in case of resource errors. Because there are now two libraries with that kind of handling, 'resourcetryagain' was moved to the auxiliary library to be shared by the libraries.
-rw-r--r--lauxlib.c46
-rw-r--r--lauxlib.h5
-rw-r--r--liolib.c54
-rw-r--r--loslib.c2
-rw-r--r--manual/manual.of14
5 files changed, 71 insertions, 50 deletions
diff --git a/lauxlib.c b/lauxlib.c
index a8f2cc2e..53b8c9bb 100644
--- a/lauxlib.c
+++ b/lauxlib.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lauxlib.c,v 1.294 2018/02/27 18:47:32 roberto Exp roberto $ 2** $Id: lauxlib.c $
3** Auxiliary functions for building Lua libraries 3** Auxiliary functions for building Lua libraries
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -292,6 +292,50 @@ LUALIB_API int luaL_execresult (lua_State *L, int stat) {
292 292
293/* 293/*
294** {====================================================== 294** {======================================================
295** 'luaL_resourcetryagain'
296** This function uses 'errno' to check whether the last error was
297** related to lack of resources (e.g., not enough memory or too many
298** open files). If so, the function performs a full garbage collection
299** to try to release resources, and then it returns 1 to signal to
300** the caller that it is worth trying again the failed operation.
301** Otherwise, it returns 0. Because error codes are not ANSI C, the
302** code must handle any combination of error codes that are defined.
303** =======================================================
304*/
305
306LUALIB_API int luaL_resourcetryagain (lua_State *L) {
307
308/* these are the resource-related errors in Linux */
309#if defined(EMFILE) || defined(ENFILE) || defined(ENOMEM)
310
311#if !defined(EMFILE) /* too many open files in the process */
312#define EMFILE -1 /* if not defined, use an impossible value */
313#endif
314
315#if !defined(ENFILE) /* too many open files in the system */
316#define ENFILE -1
317#endif
318
319#if !defined(ENOMEM) /* not enough memory */
320#define ENOMEM -1
321#endif
322
323 if (errno == EMFILE || errno == ENFILE || errno == ENOMEM) {
324 lua_gc(L, LUA_GCCOLLECT); /* try to release resources with a full GC */
325 return 1; /* signal to try again the creation */
326 }
327
328#endif
329
330 return 0; /* else, asume errors are not due to lack of resources */
331
332}
333
334/* }====================================================== */
335
336
337/*
338** {======================================================
295** Userdata's metatable manipulation 339** Userdata's metatable manipulation
296** ======================================================= 340** =======================================================
297*/ 341*/
diff --git a/lauxlib.h b/lauxlib.h
index 9f91f6a6..cd4d01e5 100644
--- a/lauxlib.h
+++ b/lauxlib.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lauxlib.h,v 1.133 2017/06/27 18:32:49 roberto Exp roberto $ 2** $Id: lauxlib.h $
3** Auxiliary functions for building Lua libraries 3** Auxiliary functions for building Lua libraries
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -77,6 +77,9 @@ LUALIB_API int (luaL_checkoption) (lua_State *L, int arg, const char *def,
77LUALIB_API int (luaL_fileresult) (lua_State *L, int stat, const char *fname); 77LUALIB_API int (luaL_fileresult) (lua_State *L, int stat, const char *fname);
78LUALIB_API int (luaL_execresult) (lua_State *L, int stat); 78LUALIB_API int (luaL_execresult) (lua_State *L, int stat);
79 79
80LUALIB_API int (luaL_resourcetryagain) (lua_State *L);
81
82
80/* predefined references */ 83/* predefined references */
81#define LUA_NOREF (-2) 84#define LUA_NOREF (-2)
82#define LUA_REFNIL (-1) 85#define LUA_REFNIL (-1)
diff --git a/liolib.c b/liolib.c
index 75e10ded..21305b8c 100644
--- a/liolib.c
+++ b/liolib.c
@@ -133,50 +133,6 @@ static int l_checkmode (const char *mode) {
133/* }====================================================== */ 133/* }====================================================== */
134 134
135 135
136/*
137** {======================================================
138** 'resourcetryagain'
139** This function uses 'errno' to check whether the last error was
140** related to lack of resources (e.g., not enough memory or too many
141** open files). If so, the function performs a full garbage collection
142** to try to release resources, and then it returns 1 to signal to
143** the caller that it is worth trying again the failed operation.
144** Otherwise, it returns 0. Because error codes are not ANSI C, the
145** code must handle any combination of error codes that are defined.
146** =======================================================
147*/
148
149static int resourcetryagain (lua_State *L) {
150
151/* these are the resource-related errors in Linux */
152#if defined(EMFILE) || defined(ENFILE) || defined(ENOMEM)
153
154#if !defined(EMFILE) /* too many open files in the process */
155#define EMFILE -1 /* if not defined, use an impossible value */
156#endif
157
158#if !defined(ENFILE) /* too many open files in the system */
159#define ENFILE -1
160#endif
161
162#if !defined(ENOMEM) /* not enough memory */
163#define ENOMEM -1
164#endif
165
166 if (errno == EMFILE || errno == ENFILE || errno == ENOMEM) {
167 lua_gc(L, LUA_GCCOLLECT); /* try to release resources with a full GC */
168 return 1; /* signal to try again the creation */
169 }
170
171#endif
172
173 return 0; /* else, asume errors are not due to lack of resources */
174
175}
176
177/* }====================================================== */
178
179
180 136
181#define IO_PREFIX "_IO_" 137#define IO_PREFIX "_IO_"
182#define IOPREF_LEN (sizeof(IO_PREFIX)/sizeof(char) - 1) 138#define IOPREF_LEN (sizeof(IO_PREFIX)/sizeof(char) - 1)
@@ -292,12 +248,12 @@ static LStream *newfile (lua_State *L) {
292 248
293/* 249/*
294** Equivalent to 'fopen', but if it fails due to a lack of resources 250** Equivalent to 'fopen', but if it fails due to a lack of resources
295** (see 'resourcetryagain'), do an "emergency" garbage collection to try 251** (see 'luaL_resourcetryagain'), do an "emergency" garbage collection
296** to close some files and then tries to open the file again. 252** to try to close some files and then tries to open the file again.
297*/ 253*/
298static FILE *trytoopen (lua_State *L, const char *path, const char *mode) { 254static FILE *trytoopen (lua_State *L, const char *path, const char *mode) {
299 FILE *f = fopen(path, mode); 255 FILE *f = fopen(path, mode);
300 if (f == NULL && resourcetryagain(L)) /* resource failure? */ 256 if (f == NULL && luaL_resourcetryagain(L)) /* resource failure? */
301 f = fopen(path, mode); /* try to open again */ 257 f = fopen(path, mode); /* try to open again */
302 return f; 258 return f;
303} 259}
@@ -336,7 +292,7 @@ static int io_popen (lua_State *L) {
336 const char *mode = luaL_optstring(L, 2, "r"); 292 const char *mode = luaL_optstring(L, 2, "r");
337 LStream *p = newprefile(L); 293 LStream *p = newprefile(L);
338 p->f = l_popen(L, filename, mode); 294 p->f = l_popen(L, filename, mode);
339 if (p->f == NULL && resourcetryagain(L)) /* resource failure? */ 295 if (p->f == NULL && luaL_resourcetryagain(L)) /* resource failure? */
340 p->f = l_popen(L, filename, mode); /* try to open again */ 296 p->f = l_popen(L, filename, mode); /* try to open again */
341 p->closef = &io_pclose; 297 p->closef = &io_pclose;
342 return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1; 298 return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1;
@@ -346,6 +302,8 @@ static int io_popen (lua_State *L) {
346static int io_tmpfile (lua_State *L) { 302static int io_tmpfile (lua_State *L) {
347 LStream *p = newfile(L); 303 LStream *p = newfile(L);
348 p->f = tmpfile(); 304 p->f = tmpfile();
305 if (p->f == NULL && luaL_resourcetryagain(L)) /* resource failure? */
306 p->f = tmpfile(); /* try to open again */
349 return (p->f == NULL) ? luaL_fileresult(L, 0, NULL) : 1; 307 return (p->f == NULL) ? luaL_fileresult(L, 0, NULL) : 1;
350} 308}
351 309
diff --git a/loslib.c b/loslib.c
index 8809e5ea..1962f55f 100644
--- a/loslib.c
+++ b/loslib.c
@@ -166,6 +166,8 @@ static int os_tmpname (lua_State *L) {
166 char buff[LUA_TMPNAMBUFSIZE]; 166 char buff[LUA_TMPNAMBUFSIZE];
167 int err; 167 int err;
168 lua_tmpnam(buff, err); 168 lua_tmpnam(buff, err);
169 if (err && luaL_resourcetryagain(L)) /* resource failure? */
170 lua_tmpnam(buff, err); /* try again */
169 if (err) 171 if (err)
170 return luaL_error(L, "unable to generate a unique filename"); 172 return luaL_error(L, "unable to generate a unique filename");
171 lua_pushstring(L, buff); 173 lua_pushstring(L, buff);
diff --git a/manual/manual.of b/manual/manual.of
index 659daa55..5a8b1b2c 100644
--- a/manual/manual.of
+++ b/manual/manual.of
@@ -5538,6 +5538,20 @@ Leaves a copy of the module on the stack.
5538 5538
5539} 5539}
5540 5540
5541@APIEntry{int luaL_resourcetryagain (lua_State *L);|
5542@apii{0,0,m}
5543
5544Try to release resources in case of errors.
5545This function uses @id{errno} to check whether the last error was
5546related to lack of resources (e.g., not enough memory or too many
5547open files).
5548If so, the function performs a full garbage collection
5549to try to release resources, and then it returns 1 to signal to
5550the caller that it is worth trying again the failed operation.
5551Otherwise, it returns 0.
5552
5553}
5554
5541@APIEntry{void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup);| 5555@APIEntry{void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup);|
5542@apii{nup,0,m} 5556@apii{nup,0,m}
5543 5557