aboutsummaryrefslogtreecommitdiff
path: root/liolib.c
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 /liolib.c
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.
Diffstat (limited to 'liolib.c')
-rw-r--r--liolib.c54
1 files changed, 6 insertions, 48 deletions
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