Skip to content

Commit 1b3f507

Browse files
committed
Bug: Call hook may be called twice when count hook yields
Took the opportunity and moved the code that controls call hooks in 'luaV_execute' into a function.
1 parent 6b51133 commit 1b3f507

File tree

4 files changed

+27
-11
lines changed

4 files changed

+27
-11
lines changed

ldebug.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -865,6 +865,28 @@ static int changedline (const Proto *p, int oldpc, int newpc) {
865865
}
866866

867867

868+
/*
869+
** Traces Lua calls. If code is running the first instruction of a function,
870+
** and function is not vararg, and it is not coming from an yield,
871+
** calls 'luaD_hookcall'. (Vararg functions will call 'luaD_hookcall'
872+
** after adjusting its variable arguments; otherwise, they could call
873+
** a line/count hook before the call hook. Functions coming from
874+
** an yield already called 'luaD_hookcall' before yielding.)
875+
*/
876+
int luaG_tracecall (lua_State *L) {
877+
CallInfo *ci = L->ci;
878+
Proto *p = ci_func(ci)->p;
879+
ci->u.l.trap = 1; /* ensure hooks will be checked */
880+
if (ci->u.l.savedpc == p->code) { /* first instruction (not resuming)? */
881+
if (p->is_vararg)
882+
return 0; /* hooks will start at VARARGPREP instruction */
883+
else if (!(ci->callstatus & CIST_HOOKYIELD)) /* not yieded? */
884+
luaD_hookcall(L, ci); /* check 'call' hook */
885+
}
886+
return 1; /* keep 'trap' on */
887+
}
888+
889+
868890
/*
869891
** Traces the execution of a Lua function. Called before the execution
870892
** of each opcode, when debug is on. 'L->oldpc' stores the last

ldebug.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ LUAI_FUNC const char *luaG_addinfo (lua_State *L, const char *msg,
5858
TString *src, int line);
5959
LUAI_FUNC l_noret luaG_errormsg (lua_State *L);
6060
LUAI_FUNC int luaG_traceexec (lua_State *L, const Instruction *pc);
61+
LUAI_FUNC int luaG_tracecall (lua_State *L);
6162

6263

6364
#endif

lstate.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ struct CallInfo {
181181
union {
182182
struct { /* only for Lua functions */
183183
const Instruction *savedpc;
184-
volatile l_signalT trap;
184+
volatile l_signalT trap; /* function is tracing lines/counts */
185185
int nextraargs; /* # of extra arguments in vararg functions */
186186
} l;
187187
struct { /* only for C functions */

lvm.c

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1157,18 +1157,11 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
11571157
startfunc:
11581158
trap = L->hookmask;
11591159
returning: /* trap already set */
1160-
cl = clLvalue(s2v(ci->func.p));
1160+
cl = ci_func(ci);
11611161
k = cl->p->k;
11621162
pc = ci->u.l.savedpc;
1163-
if (l_unlikely(trap)) {
1164-
if (pc == cl->p->code) { /* first instruction (not resuming)? */
1165-
if (cl->p->is_vararg)
1166-
trap = 0; /* hooks will start after VARARGPREP instruction */
1167-
else /* check 'call' hook */
1168-
luaD_hookcall(L, ci);
1169-
}
1170-
ci->u.l.trap = 1; /* assume trap is on, for now */
1171-
}
1163+
if (l_unlikely(trap))
1164+
trap = luaG_tracecall(L);
11721165
base = ci->func.p + 1;
11731166
/* main loop of interpreter */
11741167
for (;;) {

0 commit comments

Comments
 (0)