mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-27 14:58:30 +00:00
Fix memory deallocation while yielding in redbean. (#384)
The yielded coroutine was removed from the stack too early, leaving it not being anchored, which led to memory freed prematurely.
This commit is contained in:
parent
fb7e8ef1e6
commit
233144b19d
3 changed files with 6 additions and 4 deletions
5
third_party/lua/luacallwithtrace.c
vendored
5
third_party/lua/luacallwithtrace.c
vendored
|
@ -42,7 +42,10 @@ int LuaCallWithTrace(lua_State *L, int nargs, int nres, lua_State *C) {
|
||||||
lua_xmove(L, C, 1 + nargs);
|
lua_xmove(L, C, 1 + nargs);
|
||||||
// resume the coroutine thus executing the function
|
// resume the coroutine thus executing the function
|
||||||
status = lua_resume(C, L, nargs, &nresults);
|
status = lua_resume(C, L, nargs, &nresults);
|
||||||
lua_remove(L, 1); // remove coroutine (still) at the bottom
|
// remove coroutine (still) at the bottom, but only if not yielding
|
||||||
|
// keep it when yielding to anchor, so it's not GC-collected
|
||||||
|
// it's going to be removed at the beggining of the request handling
|
||||||
|
if (!canyield) lua_remove(L, 1);
|
||||||
if (status != LUA_OK && status != LUA_YIELD) {
|
if (status != LUA_OK && status != LUA_YIELD) {
|
||||||
// move the error message
|
// move the error message
|
||||||
lua_xmove(C, L, 1);
|
lua_xmove(C, L, 1);
|
||||||
|
|
|
@ -13,7 +13,6 @@ COSMOPOLITAN_C_START_
|
||||||
char *s = LuaFormatStack(L); \
|
char *s = LuaFormatStack(L); \
|
||||||
WARNF("lua stack should be empty!\n%s", s); \
|
WARNF("lua stack should be empty!\n%s", s); \
|
||||||
free(s); \
|
free(s); \
|
||||||
lua_settop(L, 0); \
|
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
|
|
@ -2406,6 +2406,7 @@ static int LuaCallWithYield(lua_State *L) {
|
||||||
// the second set of headers is not going to be sent
|
// the second set of headers is not going to be sent
|
||||||
lua_State *co = lua_newthread(L);
|
lua_State *co = lua_newthread(L);
|
||||||
if ((status = LuaCallWithTrace(L, 0, 0, co)) == LUA_YIELD) {
|
if ((status = LuaCallWithTrace(L, 0, 0, co)) == LUA_YIELD) {
|
||||||
|
CHECK_GT(lua_gettop(L), 0); // make sure that coroutine is anchored
|
||||||
YL = co;
|
YL = co;
|
||||||
generator = YieldGenerator;
|
generator = YieldGenerator;
|
||||||
if (!isyielding) isyielding = 1;
|
if (!isyielding) isyielding = 1;
|
||||||
|
@ -3002,9 +3003,9 @@ static char *LuaOnHttpRequest(void) {
|
||||||
lua_State *L = GL;
|
lua_State *L = GL;
|
||||||
effectivepath.p = url.path.p;
|
effectivepath.p = url.path.p;
|
||||||
effectivepath.n = url.path.n;
|
effectivepath.n = url.path.n;
|
||||||
|
lua_settop(L, 0); // clear Lua stack, as it needs to start fresh
|
||||||
lua_getglobal(L, "OnHttpRequest");
|
lua_getglobal(L, "OnHttpRequest");
|
||||||
if (LuaCallWithYield(L) == LUA_OK) {
|
if (LuaCallWithYield(L) == LUA_OK) {
|
||||||
AssertLuaStackIsEmpty(L);
|
|
||||||
return CommitOutput(GetLuaResponse());
|
return CommitOutput(GetLuaResponse());
|
||||||
} else {
|
} else {
|
||||||
LogLuaError("OnHttpRequest", lua_tostring(L, -1));
|
LogLuaError("OnHttpRequest", lua_tostring(L, -1));
|
||||||
|
@ -3012,7 +3013,6 @@ static char *LuaOnHttpRequest(void) {
|
||||||
500, "Internal Server Error",
|
500, "Internal Server Error",
|
||||||
ShouldServeCrashReportDetails() ? lua_tostring(L, -1) : NULL);
|
ShouldServeCrashReportDetails() ? lua_tostring(L, -1) : NULL);
|
||||||
lua_pop(L, 1); // pop error
|
lua_pop(L, 1); // pop error
|
||||||
AssertLuaStackIsEmpty(L);
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue