From d49b2887282b86a5e6f40a386511aa8040f3c7b0 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Mon, 15 Jun 2020 11:58:59 -0300 Subject: 'luaE_shrinkCI' shouldn't remove first free CallInfo Due to emergency collections, 'luaE_shrinkCI' can be called while Lua is building a new CallInfo, which for a while is still a free CallInfo. --- lstate.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/lstate.c b/lstate.c index 42a48436..d2e924d5 100644 --- a/lstate.c +++ b/lstate.c @@ -186,20 +186,26 @@ void luaE_freeCI (lua_State *L) { /* -** free half of the CallInfo structures not in use by a thread +** free half of the CallInfo structures not in use by a thread, +** keeping the first one. */ void luaE_shrinkCI (lua_State *L) { - CallInfo *ci = L->ci; + CallInfo *ci = L->ci->next; /* first free CallInfo */ CallInfo *next; - CallInfo *next2; /* next's next */ + if (ci == NULL) + return; /* no extra elements */ L->nCcalls += L->nci; /* add removed elements back to 'nCcalls' */ - /* while there are two nexts */ - while ((next = ci->next) != NULL && (next2 = next->next) != NULL) { + while ((next = ci->next) != NULL) { /* two extra elements? */ + CallInfo *next2 = next->next; /* next's next */ 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 */ + luaM_free(L, next); /* free next */ + if (next2 == NULL) + break; /* no more elements */ + else { + next2->previous = ci; + ci = next2; /* continue */ + } } L->nCcalls -= L->nci; /* adjust result */ } -- cgit v1.2.3-55-g6feb