[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: New param in lua_resume in Lua 5.4
- From: Andrew Gierth <andrew@...>
- Date: Fri, 10 Jul 2020 03:46:34 +0100
>>>>> "Lubos" == Lubos Uhliarik <luhliari@redhat.com> writes:
Lubos> The problem is, httpd is not possible to build with new Lua 5.4,
Lubos> since in mod_lua there are like 5 lua_resume calls. There is
Lubos> already macro:
Lubos> #define lua_resume(a,b) lua_resume(a, NULL, b)
Lubos> Is there any chance, to solve this issue only by using macro?
Lubos> Something like:
Lubos> #if LUA_VERSION_NUM > 503
Lubos> #define lua_resume(a,b) lua_resume(a, NULL, b, NULL)
Lubos> #else
Lubos> #define lua_resume(a,b) lua_resume(a, NULL, b)
Lubos> #endif
The right way to do this is to do it the other way round: rewrite the
code as if it were for lua 5.4, and then use macros to emulate the _new_
behavior on older systems.
/*
* Handle API differences for lua_resume by emulating the 5.4 API on earlier
* versions.
*/
#if LUA_VERSION_NUM < 504
static inline int
my_lua_resume(lua_State *L, lua_State *from, int nargs, int *nret)
{
#if LUA_VERSION_NUM == 501
int rc = (lua_resume)(L, nargs);
#else
int rc = (lua_resume)(L, from, nargs);
#endif
*nret = lua_gettop(L);
return rc;
}
#define lua_resume(L_,f_,a_,r_) (my_lua_resume(L_,f_,a_,r_))
#endif
But it looks like mod_lua is making several assumptions that will cause
problems with 5.4. The minor one is in passing NULL as the "from"
parameter in lua_resume; in 5.4 this will cause the coroutine to be
invoked with only a very small limit (8 calls) for the C stack nesting
depth, which now impacts the maximum function call nesting in pure Lua
code as well (80 calls).
The major one is that it's assuming that the first yielded value, if
any, from a coroutine is ending up in stack position 1. e.g.:
/* If Lua yielded, it means we have something to pass on */
if (lua_resume(L, 0) == LUA_YIELD) {
size_t olen;
const char* output = lua_tolstring(L, 1, &olen);
So I think what I'd have done here is to create a resume_and_adjust
wrapper that resumes the coroutine and then adjusts the number of
results to the expected value, like lua_call does:
static inline int
resume_and_adjust(lua_State *L, lua_State *from, int nargs, int nret)
{
#if LUA_VERSION_NUM >= 504
int actual_ret;
int rc = (lua_resume)(L, from, nargs, &actual_ret);
if (rc == 0 || rc == LUA_YIELD) {
if (nret > actual_ret)
luaL_checkstack(L, nret - actual_ret, NULL);
lua_settop(L, lua_gettop(L) + nret - actual_ret);
}
return rc;
#else
#if LUA_VERSION_NUM == 501
int rc = (lua_resume)(L, nargs);
#else
int rc = (lua_resume)(L, from, nargs);
#endif
if (rc == 0 || rc == LUA_YIELD)
lua_settop(L, nret);
return rc;
#endif
}
With this in hand, one can write:
if (resume_and_adjust(L, from, 0, 1) == LUA_YIELD) {
size_t olen;
const char *output = lua_tolstring(L, -1, &olen);
...
BTW, I don't see anywhere in mod_lua that is actually cleaning up the
stack on this code path... not sure what's going on with that.
--
Andrew.