aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2021-12-14 12:50:05 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2021-12-14 12:50:05 -0300
commit066e0f93c4901e601d93e31fb700f8f66f95feb8 (patch)
tree8b7464bbc4bbe12db97eb34f3b28874caffd1411
parent0bfc572e51d9035a615ef6e9523f736c9ffa8e57 (diff)
downloadlua-066e0f93c4901e601d93e31fb700f8f66f95feb8.tar.gz
lua-066e0f93c4901e601d93e31fb700f8f66f95feb8.tar.bz2
lua-066e0f93c4901e601d93e31fb700f8f66f95feb8.zip
Fix debug information about finalizers
The flag CIST_FIN does not mark a finalizer, but the function that was running when the finalizer was called. (So, the function did not call the finalizer, but it looks that way in the stack.)
-rw-r--r--ldebug.c54
-rw-r--r--lgc.c2
-rw-r--r--lstate.h2
-rw-r--r--testes/db.lua2
-rw-r--r--testes/gc.lua2
5 files changed, 35 insertions, 27 deletions
diff --git a/ldebug.c b/ldebug.c
index dc5f78c6..a716d95e 100644
--- a/ldebug.c
+++ b/ldebug.c
@@ -34,8 +34,8 @@
34#define noLuaClosure(f) ((f) == NULL || (f)->c.tt == LUA_VCCL) 34#define noLuaClosure(f) ((f) == NULL || (f)->c.tt == LUA_VCCL)
35 35
36 36
37static const char *funcnamefromcode (lua_State *L, CallInfo *ci, 37static const char *funcnamefromcall (lua_State *L, CallInfo *ci,
38 const char **name); 38 const char **name);
39 39
40 40
41static int currentpc (CallInfo *ci) { 41static int currentpc (CallInfo *ci) {
@@ -317,15 +317,9 @@ static void collectvalidlines (lua_State *L, Closure *f) {
317 317
318 318
319static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { 319static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) {
320 if (ci == NULL) /* no 'ci'? */ 320 /* calling function is a known function? */
321 return NULL; /* no info */ 321 if (ci != NULL && !(ci->callstatus & CIST_TAIL))
322 else if (ci->callstatus & CIST_FIN) { /* is this a finalizer? */ 322 return funcnamefromcall(L, ci->previous, name);
323 *name = "__gc";
324 return "metamethod"; /* report it as such */
325 }
326 /* calling function is a known Lua function? */
327 else if (!(ci->callstatus & CIST_TAIL) && isLua(ci->previous))
328 return funcnamefromcode(L, ci->previous, name);
329 else return NULL; /* no way to find a name */ 323 else return NULL; /* no way to find a name */
330} 324}
331 325
@@ -597,16 +591,10 @@ static const char *getobjname (const Proto *p, int lastpc, int reg,
597** Returns what the name is (e.g., "for iterator", "method", 591** Returns what the name is (e.g., "for iterator", "method",
598** "metamethod") and sets '*name' to point to the name. 592** "metamethod") and sets '*name' to point to the name.
599*/ 593*/
600static const char *funcnamefromcode (lua_State *L, CallInfo *ci, 594static const char *funcnamefromcode (lua_State *L, const Proto *p,
601 const char **name) { 595 int pc, const char **name) {
602 TMS tm = (TMS)0; /* (initial value avoids warnings) */ 596 TMS tm = (TMS)0; /* (initial value avoids warnings) */
603 const Proto *p = ci_func(ci)->p; /* calling function */
604 int pc = currentpc(ci); /* calling instruction index */
605 Instruction i = p->code[pc]; /* calling instruction */ 597 Instruction i = p->code[pc]; /* calling instruction */
606 if (ci->callstatus & CIST_HOOKED) { /* was it called inside a hook? */
607 *name = "?";
608 return "hook";
609 }
610 switch (GET_OPCODE(i)) { 598 switch (GET_OPCODE(i)) {
611 case OP_CALL: 599 case OP_CALL:
612 case OP_TAILCALL: 600 case OP_TAILCALL:
@@ -643,6 +631,26 @@ static const char *funcnamefromcode (lua_State *L, CallInfo *ci,
643 return "metamethod"; 631 return "metamethod";
644} 632}
645 633
634
635/*
636** Try to find a name for a function based on how it was called.
637*/
638static const char *funcnamefromcall (lua_State *L, CallInfo *ci,
639 const char **name) {
640 if (ci->callstatus & CIST_HOOKED) { /* was it called inside a hook? */
641 *name = "?";
642 return "hook";
643 }
644 else if (ci->callstatus & CIST_FIN) { /* was it called as a finalizer? */
645 *name = "__gc";
646 return "metamethod"; /* report it as such */
647 }
648 else if (isLua(ci))
649 return funcnamefromcode(L, ci_func(ci)->p, currentpc(ci), name);
650 else
651 return NULL;
652}
653
646/* }====================================================== */ 654/* }====================================================== */
647 655
648 656
@@ -728,14 +736,14 @@ l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) {
728 736
729 737
730/* 738/*
731** Raise an error for calling a non-callable object. Try to find 739** Raise an error for calling a non-callable object. Try to find a name
732** a name for the object based on the code that made the call 740** for the object based on how it was called ('funcnamefromcall'); if it
733** ('funcnamefromcode'); if it cannot get a name there, try 'varinfo'. 741** cannot get a name there, try 'varinfo'.
734*/ 742*/
735l_noret luaG_callerror (lua_State *L, const TValue *o) { 743l_noret luaG_callerror (lua_State *L, const TValue *o) {
736 CallInfo *ci = L->ci; 744 CallInfo *ci = L->ci;
737 const char *name = NULL; /* to avoid warnings */ 745 const char *name = NULL; /* to avoid warnings */
738 const char *kind = (isLua(ci)) ? funcnamefromcode(L, ci, &name) : NULL; 746 const char *kind = funcnamefromcall(L, ci, &name);
739 const char *extra = kind ? formatvarinfo(L, kind, name) : varinfo(L, o); 747 const char *extra = kind ? formatvarinfo(L, kind, name) : varinfo(L, o);
740 typeerror(L, o, "call", extra); 748 typeerror(L, o, "call", extra);
741} 749}
diff --git a/lgc.c b/lgc.c
index 7d0b5e4f..d3f5b5b7 100644
--- a/lgc.c
+++ b/lgc.c
@@ -917,7 +917,7 @@ static void GCTM (lua_State *L) {
917 L->allowhook = oldah; /* restore hooks */ 917 L->allowhook = oldah; /* restore hooks */
918 g->gcstp = oldgcstp; /* restore state */ 918 g->gcstp = oldgcstp; /* restore state */
919 if (l_unlikely(status != LUA_OK)) { /* error while running __gc? */ 919 if (l_unlikely(status != LUA_OK)) { /* error while running __gc? */
920 luaE_warnerror(L, "__gc metamethod"); 920 luaE_warnerror(L, "__gc");
921 L->top--; /* pops error object */ 921 L->top--; /* pops error object */
922 } 922 }
923 } 923 }
diff --git a/lstate.h b/lstate.h
index 7886d891..61e82cde 100644
--- a/lstate.h
+++ b/lstate.h
@@ -209,7 +209,7 @@ typedef struct CallInfo {
209#define CIST_YPCALL (1<<4) /* doing a yieldable protected call */ 209#define CIST_YPCALL (1<<4) /* doing a yieldable protected call */
210#define CIST_TAIL (1<<5) /* call was tail called */ 210#define CIST_TAIL (1<<5) /* call was tail called */
211#define CIST_HOOKYIELD (1<<6) /* last hook called yielded */ 211#define CIST_HOOKYIELD (1<<6) /* last hook called yielded */
212#define CIST_FIN (1<<7) /* call is running a finalizer */ 212#define CIST_FIN (1<<7) /* function "called" a finalizer */
213#define CIST_TRAN (1<<8) /* 'ci' has transfer information */ 213#define CIST_TRAN (1<<8) /* 'ci' has transfer information */
214#define CIST_CLSRET (1<<9) /* function is closing tbc variables */ 214#define CIST_CLSRET (1<<9) /* function is closing tbc variables */
215/* Bits 10-12 are used for CIST_RECST (see below) */ 215/* Bits 10-12 are used for CIST_RECST (see below) */
diff --git a/testes/db.lua b/testes/db.lua
index e0699724..f891e9b8 100644
--- a/testes/db.lua
+++ b/testes/db.lua
@@ -887,7 +887,7 @@ do -- testing debug info for finalizers
887 887
888 -- create a piece of garbage with a finalizer 888 -- create a piece of garbage with a finalizer
889 setmetatable({}, {__gc = function () 889 setmetatable({}, {__gc = function ()
890 local t = debug.getinfo(2) -- get callee information 890 local t = debug.getinfo(1) -- get function information
891 assert(t.namewhat == "metamethod") 891 assert(t.namewhat == "metamethod")
892 name = t.name 892 name = t.name
893 end}) 893 end})
diff --git a/testes/gc.lua b/testes/gc.lua
index d865cb28..381c5548 100644
--- a/testes/gc.lua
+++ b/testes/gc.lua
@@ -371,7 +371,7 @@ if T then
371 371
372 warn("@on"); warn("@store") 372 warn("@on"); warn("@store")
373 collectgarbage() 373 collectgarbage()
374 assert(string.find(_WARN, "error in __gc metamethod")) 374 assert(string.find(_WARN, "error in __gc"))
375 assert(string.match(_WARN, "@(.-)@") == "expected"); _WARN = false 375 assert(string.match(_WARN, "@(.-)@") == "expected"); _WARN = false
376 for i = 8, 10 do assert(s[i]) end 376 for i = 8, 10 do assert(s[i]) end
377 377