diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2021-12-14 12:50:05 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2021-12-14 12:50:05 -0300 |
commit | 066e0f93c4901e601d93e31fb700f8f66f95feb8 (patch) | |
tree | 8b7464bbc4bbe12db97eb34f3b28874caffd1411 | |
parent | 0bfc572e51d9035a615ef6e9523f736c9ffa8e57 (diff) | |
download | lua-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.c | 54 | ||||
-rw-r--r-- | lgc.c | 2 | ||||
-rw-r--r-- | lstate.h | 2 | ||||
-rw-r--r-- | testes/db.lua | 2 | ||||
-rw-r--r-- | testes/gc.lua | 2 |
5 files changed, 35 insertions, 27 deletions
@@ -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 | ||
37 | static const char *funcnamefromcode (lua_State *L, CallInfo *ci, | 37 | static const char *funcnamefromcall (lua_State *L, CallInfo *ci, |
38 | const char **name); | 38 | const char **name); |
39 | 39 | ||
40 | 40 | ||
41 | static int currentpc (CallInfo *ci) { | 41 | static int currentpc (CallInfo *ci) { |
@@ -317,15 +317,9 @@ static void collectvalidlines (lua_State *L, Closure *f) { | |||
317 | 317 | ||
318 | 318 | ||
319 | static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { | 319 | static 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 | */ |
600 | static const char *funcnamefromcode (lua_State *L, CallInfo *ci, | 594 | static 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 | */ | ||
638 | static 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 | */ |
735 | l_noret luaG_callerror (lua_State *L, const TValue *o) { | 743 | l_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 | } |
@@ -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 | } |
@@ -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 | ||