aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2019-08-16 09:51:54 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2019-08-16 09:51:54 -0300
commitca13be9af784b7288d3a07d9b5bccb329086e885 (patch)
treec027419f98064d681518a4130439920a13a11b06
parenta1d8eb27431c02c4529be1efd92143ad65434f3a (diff)
downloadlua-ca13be9af784b7288d3a07d9b5bccb329086e885.tar.gz
lua-ca13be9af784b7288d3a07d9b5bccb329086e885.tar.bz2
lua-ca13be9af784b7288d3a07d9b5bccb329086e885.zip
Supressed errors in '__close' generate warnings
-rw-r--r--lauxlib.c4
-rw-r--r--lfunc.c6
-rw-r--r--lgc.c7
-rw-r--r--lstate.c16
-rw-r--r--lstate.h1
-rw-r--r--ltests.c10
-rw-r--r--manual/manual.of2
-rw-r--r--testes/all.lua4
-rw-r--r--testes/coroutine.lua5
-rw-r--r--testes/locals.lua152
10 files changed, 164 insertions, 43 deletions
diff --git a/lauxlib.c b/lauxlib.c
index ba1980b7..014e7052 100644
--- a/lauxlib.c
+++ b/lauxlib.c
@@ -1010,9 +1010,9 @@ static int panic (lua_State *L) {
1010static void warnf (void *ud, const char *message, int tocont) { 1010static void warnf (void *ud, const char *message, int tocont) {
1011 int *warnstate = (int *)ud; 1011 int *warnstate = (int *)ud;
1012 if (*warnstate != 2 && !tocont && *message == '@') { /* control message? */ 1012 if (*warnstate != 2 && !tocont && *message == '@') { /* control message? */
1013 if (strcmp(message + 1, "off") == 0) 1013 if (strcmp(message, "@off") == 0)
1014 *warnstate = 0; 1014 *warnstate = 0;
1015 else if (strcmp(message + 1, "on") == 0) 1015 else if (strcmp(message, "@on") == 0)
1016 *warnstate = 1; 1016 *warnstate = 1;
1017 return; 1017 return;
1018 } 1018 }
diff --git a/lfunc.c b/lfunc.c
index 8f39f6b0..1e61f03f 100644
--- a/lfunc.c
+++ b/lfunc.c
@@ -164,8 +164,12 @@ static int callclosemth (lua_State *L, StkId level, int status) {
164 int newstatus = luaD_pcall(L, callclose, NULL, oldtop, 0); 164 int newstatus = luaD_pcall(L, callclose, NULL, oldtop, 0);
165 if (newstatus != LUA_OK && status == CLOSEPROTECT) /* first error? */ 165 if (newstatus != LUA_OK && status == CLOSEPROTECT) /* first error? */
166 status = newstatus; /* this will be the new error */ 166 status = newstatus; /* this will be the new error */
167 else /* leave original error (or nil) on top */ 167 else {
168 if (newstatus != LUA_OK) /* supressed error? */
169 luaE_warnerror(L, "__close metamethod");
170 /* leave original error (or nil) on top */
168 L->top = restorestack(L, oldtop); 171 L->top = restorestack(L, oldtop);
172 }
169 } 173 }
170 /* else no metamethod; ignore this case and keep original error */ 174 /* else no metamethod; ignore this case and keep original error */
171 } 175 }
diff --git a/lgc.c b/lgc.c
index 75670c0a..f24074f9 100644
--- a/lgc.c
+++ b/lgc.c
@@ -854,12 +854,7 @@ static void GCTM (lua_State *L) {
854 L->allowhook = oldah; /* restore hooks */ 854 L->allowhook = oldah; /* restore hooks */
855 g->gcrunning = running; /* restore state */ 855 g->gcrunning = running; /* restore state */
856 if (unlikely(status != LUA_OK)) { /* error while running __gc? */ 856 if (unlikely(status != LUA_OK)) { /* error while running __gc? */
857 const char *msg = (ttisstring(s2v(L->top - 1))) 857 luaE_warnerror(L, "__gc metamethod");
858 ? svalue(s2v(L->top - 1))
859 : "error object is not a string";
860 luaE_warning(L, "error in __gc metamethod (", 1);
861 luaE_warning(L, msg, 1);
862 luaE_warning(L, ")", 0);
863 L->top--; /* pops error object */ 858 L->top--; /* pops error object */
864 } 859 }
865 } 860 }
diff --git a/lstate.c b/lstate.c
index d4bc53eb..86cd5fb8 100644
--- a/lstate.c
+++ b/lstate.c
@@ -443,3 +443,19 @@ void luaE_warning (lua_State *L, const char *msg, int tocont) {
443} 443}
444 444
445 445
446/*
447** Generate a warning from an error message
448*/
449void luaE_warnerror (lua_State *L, const char *where) {
450 TValue *errobj = s2v(L->top - 1); /* error object */
451 const char *msg = (ttisstring(errobj))
452 ? svalue(errobj)
453 : "error object is not a string";
454 /* produce warning "error in %s (%s)" (where, msg) */
455 luaE_warning(L, "error in ", 1);
456 luaE_warning(L, where, 1);
457 luaE_warning(L, " (", 1);
458 luaE_warning(L, msg, 1);
459 luaE_warning(L, ")", 0);
460}
461
diff --git a/lstate.h b/lstate.h
index 03448b82..638c1e5c 100644
--- a/lstate.h
+++ b/lstate.h
@@ -355,6 +355,7 @@ LUAI_FUNC void luaE_freeCI (lua_State *L);
355LUAI_FUNC void luaE_shrinkCI (lua_State *L); 355LUAI_FUNC void luaE_shrinkCI (lua_State *L);
356LUAI_FUNC void luaE_enterCcall (lua_State *L); 356LUAI_FUNC void luaE_enterCcall (lua_State *L);
357LUAI_FUNC void luaE_warning (lua_State *L, const char *msg, int tocont); 357LUAI_FUNC void luaE_warning (lua_State *L, const char *msg, int tocont);
358LUAI_FUNC void luaE_warnerror (lua_State *L, const char *where);
358 359
359 360
360#define luaE_exitCcall(L) ((L)->nCcalls++) 361#define luaE_exitCcall(L) ((L)->nCcalls++)
diff --git a/ltests.c b/ltests.c
index fd55fc31..b460d018 100644
--- a/ltests.c
+++ b/ltests.c
@@ -95,15 +95,15 @@ static void warnf (void *ud, const char *msg, int tocont) {
95 if (!lasttocont && !tocont && *msg == '@') { /* control message? */ 95 if (!lasttocont && !tocont && *msg == '@') { /* control message? */
96 if (buff[0] != '\0') 96 if (buff[0] != '\0')
97 badexit("Control warning during warning: %s\naborting...\n", msg); 97 badexit("Control warning during warning: %s\naborting...\n", msg);
98 if (strcmp(msg + 1, "off") == 0) 98 if (strcmp(msg, "@off") == 0)
99 onoff = 0; 99 onoff = 0;
100 else if (strcmp(msg + 1, "on") == 0) 100 else if (strcmp(msg, "@on") == 0)
101 onoff = 1; 101 onoff = 1;
102 else if (strcmp(msg + 1, "normal") == 0) 102 else if (strcmp(msg, "@normal") == 0)
103 mode = 0; 103 mode = 0;
104 else if (strcmp(msg + 1, "allow") == 0) 104 else if (strcmp(msg, "@allow") == 0)
105 mode = 1; 105 mode = 1;
106 else if (strcmp(msg + 1, "store") == 0) 106 else if (strcmp(msg, "@store") == 0)
107 mode = 2; 107 mode = 2;
108 else 108 else
109 badexit("Invalid control warning in test mode: %s\naborting...\n", msg); 109 badexit("Invalid control warning in test mode: %s\naborting...\n", msg);
diff --git a/manual/manual.of b/manual/manual.of
index 8c71c613..bb6ae884 100644
--- a/manual/manual.of
+++ b/manual/manual.of
@@ -1556,7 +1556,7 @@ However, Lua may call the method one more time.
1556After an error, 1556After an error,
1557the other pending closing methods will still be called. 1557the other pending closing methods will still be called.
1558Errors in these methods 1558Errors in these methods
1559interrupt the respective method, 1559interrupt the respective method and generate a warning,
1560but are otherwise ignored; 1560but are otherwise ignored;
1561the error reported is only the original one. 1561the error reported is only the original one.
1562 1562
diff --git a/testes/all.lua b/testes/all.lua
index 5d698d4b..42809b9a 100644
--- a/testes/all.lua
+++ b/testes/all.lua
@@ -209,12 +209,12 @@ if #msgs > 0 then
209 warn("#tests not performed:\n ", m, "\n") 209 warn("#tests not performed:\n ", m, "\n")
210end 210end
211 211
212print("(there should be two warnings now)")
213warn("#This is ", "an expected", " warning")
212warn("@off") 214warn("@off")
213warn("******** THIS WARNING SHOULD NOT APPEAR **********") 215warn("******** THIS WARNING SHOULD NOT APPEAR **********")
214warn("******** THIS WARNING ALSO SHOULD NOT APPEAR **********") 216warn("******** THIS WARNING ALSO SHOULD NOT APPEAR **********")
215warn("@on") 217warn("@on")
216print("(there should be two warnings now)")
217warn("#This is ", "an expected", " warning")
218warn("#This is", " another one") 218warn("#This is", " another one")
219 219
220-- no test module should define 'debug' 220-- no test module should define 'debug'
diff --git a/testes/coroutine.lua b/testes/coroutine.lua
index 457374ca..79c72a9d 100644
--- a/testes/coroutine.lua
+++ b/testes/coroutine.lua
@@ -168,7 +168,7 @@ do
168 local y <close> = func2close(function (self,err) 168 local y <close> = func2close(function (self,err)
169 if (err ~= 111) then os.exit(false) end -- should not happen 169 if (err ~= 111) then os.exit(false) end -- should not happen
170 x = 200 170 x = 200
171 error(200) 171 error("200")
172 end) 172 end)
173 local x <close> = func2close(function (self, err) 173 local x <close> = func2close(function (self, err)
174 assert(err == nil); error(111) 174 assert(err == nil); error(111)
@@ -177,7 +177,10 @@ do
177 end) 177 end)
178 coroutine.resume(co) 178 coroutine.resume(co)
179 assert(x == 0) 179 assert(x == 0)
180 _WARN = nil; warn("@off"); warn("@store")
180 local st, msg = coroutine.close(co) 181 local st, msg = coroutine.close(co)
182 warn("@on"); warn("@normal")
183 assert(_WARN == nil or string.find(_WARN, "200"))
181 assert(st == false and coroutine.status(co) == "dead" and msg == 111) 184 assert(st == false and coroutine.status(co) == "dead" and msg == 111)
182 assert(x == 200) 185 assert(x == 200)
183 186
diff --git a/testes/locals.lua b/testes/locals.lua
index 99fa79cd..595e107a 100644
--- a/testes/locals.lua
+++ b/testes/locals.lua
@@ -286,57 +286,149 @@ do
286end 286end
287 287
288 288
289do -- errors in __close 289-- auxiliary functions for testing warnings in '__close'
290 local log = {} 290local function prepwarn ()
291 local function foo (err) 291 warn("@off") -- do not show (lots of) warnings
292 if not T then
293 _WARN = "OFF" -- signal that warnings are not being captured
294 else
295 warn("@store") -- to test the warnings
296 end
297end
298
299
300local function endwarn ()
301 assert(T or _WARN == "OFF")
302 warn("@on") -- back to normal
303 warn("@normal")
304 _WARN = nil
305end
306
307
308local function checkwarn (msg)
309 assert(_WARN == "OFF" or string.find(_WARN, msg))
310end
311
312
313do print("testing errors in __close")
314
315 prepwarn()
316
317 -- original error is in __close
318 local function foo ()
319
292 local x <close> = 320 local x <close> =
293 func2close(function (self, msg) log[#log + 1] = msg; error(1) end) 321 func2close(function (self, msg)
322 assert(string.find(msg, "@z"))
323 error("@x")
324 end)
325
294 local x1 <close> = 326 local x1 <close> =
295 func2close(function (self, msg) log[#log + 1] = msg; end) 327 func2close(function (self, msg)
328 checkwarn("@y")
329 assert(string.find(msg, "@z"))
330 end)
331
296 local gc <close> = func2close(function () collectgarbage() end) 332 local gc <close> = func2close(function () collectgarbage() end)
333
297 local y <close> = 334 local y <close> =
298 func2close(function (self, msg) log[#log + 1] = msg; error(2) end) 335 func2close(function (self, msg)
336 assert(string.find(msg, "@z")) -- error in 'z'
337 error("@y")
338 end)
339
340 local first = true
299 local z <close> = 341 local z <close> =
342 -- 'z' close is called twice
300 func2close(function (self, msg) 343 func2close(function (self, msg)
301 log[#log + 1] = (msg or 10) + 1; 344 if first then
302 error(3) 345 assert(msg == nil)
346 first = false
347 else
348 assert(string.find(msg, "@z")) -- own error
349 end
350 error("@z")
303 end) 351 end)
304 if err then error(4) end 352
353 return 200
305 end 354 end
355
306 local stat, msg = pcall(foo, false) 356 local stat, msg = pcall(foo, false)
307 assert(msg == 3) 357 assert(string.find(msg, "@z"))
308 -- 'z' close is called twice 358 checkwarn("@x")
309 assert(log[1] == 11 and log[2] == 4 and log[3] == 3 and log[4] == 3 359
310 and log[5] == 3 and #log == 5) 360
361 -- original error not in __close
362 local function foo ()
363
364 local x <close> =
365 func2close(function (self, msg)
366 assert(msg == 4)
367 end)
368
369 local x1 <close> =
370 func2close(function (self, msg)
371 checkwarn("@y")
372 assert(msg == 4)
373 error("@x1")
374 end)
375
376 local gc <close> = func2close(function () collectgarbage() end)
377
378 local y <close> =
379 func2close(function (self, msg)
380 assert(msg == 4) -- error in body
381 error("@y")
382 end)
383
384 local first = true
385 local z <close> =
386 func2close(function (self, msg)
387 checkwarn("@z")
388 -- 'z' close is called once
389 assert(first and msg == 4)
390 first = false
391 error("@z")
392 end)
393
394 error(4) -- original error
395 end
311 396
312 log = {}
313 local stat, msg = pcall(foo, true) 397 local stat, msg = pcall(foo, true)
314 assert(msg == 4) 398 assert(msg == 4)
315 -- 'z' close is called once 399 checkwarn("@x1") -- last error
316 assert(log[1] == 5 and log[2] == 4 and log[3] == 4 and log[4] == 4
317 and #log == 4)
318 400
319 -- error leaving a block 401 -- error leaving a block
320 local function foo (...) 402 local function foo (...)
321 do 403 do
322 local x1 <close> = func2close(function () error("Y") end) 404 local x1 <close> =
323 local x123 <close> = func2close(function () error("X") end) 405 func2close(function ()
406 checkwarn("@X")
407 error("@Y")
408 end)
409
410 local x123 <close> =
411 func2close(function ()
412 error("@X")
413 end)
324 end 414 end
415 os.exit(false) -- should not run
325 end 416 end
326 417
327 local st, msg = xpcall(foo, debug.traceback) 418 local st, msg = xpcall(foo, debug.traceback)
328 assert(string.match(msg, "^[^ ]* X")) 419 assert(string.match(msg, "^[^ ]* @X"))
329 assert(string.find(msg, "in metamethod 'close'")) 420 assert(string.find(msg, "in metamethod 'close'"))
330 421
331 -- error in toclose in vararg function 422 -- error in toclose in vararg function
332 local function foo (...) 423 local function foo (...)
333 local x123 <close> = func2close(function () error("X") end) 424 local x123 <close> = func2close(function () error("@X") end)
334 end 425 end
335 426
336 local st, msg = xpcall(foo, debug.traceback) 427 local st, msg = xpcall(foo, debug.traceback)
337 assert(string.match(msg, "^[^ ]* X")) 428 assert(string.match(msg, "^[^ ]* @X"))
338 429
339 assert(string.find(msg, "in metamethod 'close'")) 430 assert(string.find(msg, "in metamethod 'close'"))
431 endwarn()
340end 432end
341 433
342 434
@@ -361,6 +453,8 @@ end
361 453
362if rawget(_G, "T") then 454if rawget(_G, "T") then
363 455
456 warn("@off")
457
364 -- memory error inside closing function 458 -- memory error inside closing function
365 local function foo () 459 local function foo ()
366 local y <close> = func2close(function () T.alloccount() end) 460 local y <close> = func2close(function () T.alloccount() end)
@@ -437,7 +531,7 @@ if rawget(_G, "T") then
437 531
438 local s = string.rep("a", lim) 532 local s = string.rep("a", lim)
439 533
440 -- concat this table needs two buffer resizes (one for each 's') 534 -- concat this table needs two buffer resizes (one for each 's')
441 local a = {s, s} 535 local a = {s, s}
442 536
443 collectgarbage() 537 collectgarbage()
@@ -472,6 +566,8 @@ if rawget(_G, "T") then
472 566
473 print'+' 567 print'+'
474 end 568 end
569
570 warn("@on")
475end 571end
476 572
477 573
@@ -501,17 +597,20 @@ end
501 597
502 598
503do 599do
600 prepwarn()
601
504 -- error in a wrapped coroutine raising errors when closing a variable 602 -- error in a wrapped coroutine raising errors when closing a variable
505 local x = 0 603 local x = 0
506 local co = coroutine.wrap(function () 604 local co = coroutine.wrap(function ()
507 local xx <close> = func2close(function () x = x + 1; error("YYY") end) 605 local xx <close> = func2close(function () x = x + 1; error("@YYY") end)
508 local xv <close> = func2close(function () x = x + 1; error("XXX") end) 606 local xv <close> = func2close(function () x = x + 1; error("@XXX") end)
509 coroutine.yield(100) 607 coroutine.yield(100)
510 error(200) 608 error(200)
511 end) 609 end)
512 assert(co() == 100); assert(x == 0) 610 assert(co() == 100); assert(x == 0)
513 local st, msg = pcall(co); assert(x == 2) 611 local st, msg = pcall(co); assert(x == 2)
514 assert(not st and msg == 200) -- should get first error raised 612 assert(not st and msg == 200) -- should get first error raised
613 checkwarn("@YYY")
515 614
516 local x = 0 615 local x = 0
517 local y = 0 616 local y = 0
@@ -526,6 +625,9 @@ do
526 assert(x == 2 and y == 1) -- first close is called twice 625 assert(x == 2 and y == 1) -- first close is called twice
527 -- should get first error raised 626 -- should get first error raised
528 assert(not st and string.find(msg, "%w+%.%w+:%d+: XXX")) 627 assert(not st and string.find(msg, "%w+%.%w+:%d+: XXX"))
628 checkwarn("YYY")
629
630 endwarn()
529end 631end
530 632
531 633