From 17dbaa8639505c9ad1a9946591f5960123fbd741 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Fri, 22 May 2020 11:40:34 -0300 Subject: [PATCH] Improvements in the handling of signals Added 'volatile' to 'l_signalT' variables plus some minor changes. --- ldebug.c | 20 +++++++++++--------- ldo.c | 10 +++++----- lstate.c | 9 +++++---- lstate.h | 4 ++-- lua.c | 3 ++- 5 files changed, 25 insertions(+), 21 deletions(-) diff --git a/ldebug.c b/ldebug.c index eaac16f7..afdc2b74 100644 --- a/ldebug.c +++ b/ldebug.c @@ -107,13 +107,15 @@ static int getcurrentline (CallInfo *ci) { /* -** This function can be called asynchronously (e.g. during a signal), -** under "reasonable" assumptions. A new 'ci' is completely linked -** in the list before it becomes part of the "active" list, and -** we assume that pointers are atomic (see comment in next function). -** (If we traverse one more item, there is no problem. If we traverse -** one less item, the worst that can happen is that the signal will -** not interrupt the script.) +** Set 'trap' for all active Lua frames. +** This function can be called during a signal, under "reasonable" +** assumptions. A new 'ci' is completely linked in the list before it +** becomes part of the "active" list, and we assume that pointers are +** atomic; see comment in next function. +** (A compiler doing interprocedural optimizations could, theoretically, +** reorder memory writes in such a way that the list could be +** temporarily broken while inserting a new element. We simply assume it +** has no good reasons to do that.) */ static void settraps (CallInfo *ci) { for (; ci != NULL; ci = ci->previous) @@ -123,8 +125,8 @@ static void settraps (CallInfo *ci) { /* -** This function can be called asynchronously (e.g. during a signal), -** under "reasonable" assumptions. +** This function can be called during a signal, under "reasonable" +** assumptions. ** Fields 'oldpc', 'basehookcount', and 'hookcount' (set by ** 'resethookcount') are for debug only, and it is no problem if they ** get arbitrary values (causes at most one wrong hook call). 'hookmask' diff --git a/ldo.c b/ldo.c index 64fe2915..c563b1d9 100644 --- a/ldo.c +++ b/ldo.c @@ -422,7 +422,7 @@ void luaD_poscall (lua_State *L, CallInfo *ci, int nres) { -#define next_ci(L) (L->ci = (L->ci->next ? L->ci->next : luaE_extendCI(L))) +#define next_ci(L) (L->ci->next ? L->ci->next : luaE_extendCI(L)) /* @@ -466,13 +466,13 @@ void luaD_call (lua_State *L, StkId func, int nresults) { f = fvalue(s2v(func)); Cfunc: { int n; /* number of returns */ - CallInfo *ci; + CallInfo *ci = next_ci(L); checkstackp(L, LUA_MINSTACK, func); /* ensure minimum stack size */ - ci = next_ci(L); ci->nresults = nresults; ci->callstatus = CIST_C; ci->top = L->top + LUA_MINSTACK; ci->func = func; + L->ci = ci; lua_assert(ci->top <= L->stack_last); if (L->hookmask & LUA_MASKCALL) { int narg = cast_int(L->top - func) - 1; @@ -486,18 +486,18 @@ void luaD_call (lua_State *L, StkId func, int nresults) { break; } case LUA_VLCL: { /* Lua function */ - CallInfo *ci; + CallInfo *ci = next_ci(L); Proto *p = clLvalue(s2v(func))->p; int narg = cast_int(L->top - func) - 1; /* number of real arguments */ int nfixparams = p->numparams; int fsize = p->maxstacksize; /* frame size */ checkstackp(L, fsize, func); - ci = next_ci(L); ci->nresults = nresults; ci->u.l.savedpc = p->code; /* starting point */ ci->callstatus = 0; ci->top = func + 1 + fsize; ci->func = func; + L->ci = ci; for (; narg < nfixparams; narg++) setnilvalue(s2v(L->top++)); /* complete missing arguments */ lua_assert(ci->top <= L->stack_last); diff --git a/lstate.c b/lstate.c index 8fba70d7..42a48436 100644 --- a/lstate.c +++ b/lstate.c @@ -190,14 +190,15 @@ void luaE_freeCI (lua_State *L) { */ void luaE_shrinkCI (lua_State *L) { CallInfo *ci = L->ci; + CallInfo *next; CallInfo *next2; /* next's next */ L->nCcalls += L->nci; /* add removed elements back to 'nCcalls' */ /* while there are two nexts */ - while (ci->next != NULL && (next2 = ci->next->next) != NULL) { - luaM_free(L, ci->next); /* free next */ - L->nci--; - ci->next = next2; /* remove 'next' from the list */ + while ((next = ci->next) != NULL && (next2 = next->next) != NULL) { + ci->next = next2; /* remove next from the list */ next2->previous = ci; + luaM_free(L, next); /* free next */ + L->nci--; ci = next2; /* keep next's next */ } L->nCcalls -= L->nci; /* adjust result */ diff --git a/lstate.h b/lstate.h index df9148eb..2e8bd6c4 100644 --- a/lstate.h +++ b/lstate.h @@ -173,7 +173,7 @@ typedef struct CallInfo { union { struct { /* only for Lua functions */ const Instruction *savedpc; - l_signalT trap; + volatile l_signalT trap; int nextraargs; /* # of extra arguments in vararg functions */ } l; struct { /* only for C functions */ @@ -300,7 +300,7 @@ struct lua_State { int stacksize; int basehookcount; int hookcount; - l_signalT hookmask; + volatile l_signalT hookmask; }; diff --git a/lua.c b/lua.c index 18f53c30..454ce12f 100644 --- a/lua.c +++ b/lua.c @@ -54,8 +54,9 @@ static void lstop (lua_State *L, lua_Debug *ar) { ** interpreter. */ static void laction (int i) { + int flag = LUA_MASKCALL | LUA_MASKRET | LUA_MASKLINE | LUA_MASKCOUNT; signal(i, SIG_DFL); /* if another SIGINT happens, terminate process */ - lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1); + lua_sethook(globalL, lstop, flag, 1); }