New param in lua_resume in Lua 5.4

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

New param in lua_resume in Lua 5.4

Lubos Uhliarik
Hi all,

I just found out, that there has been added new param to function lua_resume.

New definition in Lua 5.4 is following:

int lua_resume (lua_State *L, lua_State *from, int nargs,
                          int *nresults);


Do you have any idea, how I need to rewrite the code, if in old code we use just
lua_resume(L, NULL, x) ?

I'm sorry if it is a stupid question, but I'm total newbie in Lua.

Best,

--
Lubos Uhliarik
Software Engineer - EMEA ENG Developer Experience
RH - Brno - TPB-C - 1D221
IRC: zero_byte at irc.freenode.net

RED HAT | TRIED. TESTED. TRUSTED.
Every airline in the Fortune 500 relies on Red Hat.
Find out why at http://www.redhat.com/en/about/trusted

Red Hat Inc. http://cz.redhat.com
Reply | Threaded
Open this post in threaded view
|

Re: New param in lua_resume in Lua 5.4

Joseph C. Sible
On Thu, Jul 9, 2020 at 11:46 AM Lubos Uhliarik <[hidden email]> wrote:

>
> I just found out, that there has been added new param to function lua_resume.
>
> New definition in Lua 5.4 is following:
>
> int lua_resume (lua_State *L, lua_State *from, int nargs,
>                           int *nresults);
>
>
> Do you have any idea, how I need to rewrite the code, if in old code we use just
> lua_resume(L, NULL, x) ?

It depends on the context of the code around it. Basically, wherever
you used lua_gettop(L) before, you want to use nres from the out
parameter now. For example, if you had this before:

/* set up for the call to lua_resume */
int status = lua_resume(L, NULL, x);
/* check status */
int nres = lua_gettop(L);
/* do stuff with nres */

Then you'd want to do this now:

/* set up for the call to lua_resume */
int nres;
int status = lua_resume(L, NULL, x, &nres);
/* check status */
/* do stuff with nres */

Joseph C. Sible
Reply | Threaded
Open this post in threaded view
|

Re: New param in lua_resume in Lua 5.4

Lubos Uhliarik
Hi Joseph,

thanks for your answer! Is it still possible to get nres in the old way?

The problem is, httpd is not possible to build with new Lua 5.4, since in mod_lua
there are like 5 lua_resume calls. There is already macro:

#define lua_resume(a,b)    lua_resume(a, NULL, b)

Is there any chance, to solve this issue only by using macro? Something like:

#if LUA_VERSION_NUM > 503
#define lua_resume(a,b)    lua_resume(a, NULL, b, NULL)
#else
#define lua_resume(a,b)    lua_resume(a, NULL, b)
#endif


lua_gettop(L) is in the code used like 7 times and it is far away from lua_resume
function calls, so I suppose it won't be so easy to rewrite it, if lua_gettop can NOT
be used anymore. Or is it possible to use lua_gettop like in version 5.3 and pass NULL to the
fourth param, as I mentioned above?

Best,

----- Original Message -----

> From: "Joseph C. Sible" <[hidden email]>
> To: "Lua mailing list" <[hidden email]>
> Sent: Thursday, July 9, 2020 8:31:33 PM
> Subject: Re: New param in lua_resume in Lua 5.4
>
> On Thu, Jul 9, 2020 at 11:46 AM Lubos Uhliarik <[hidden email]> wrote:
> >
> > I just found out, that there has been added new param to function
> > lua_resume.
> >
> > New definition in Lua 5.4 is following:
> >
> > int lua_resume (lua_State *L, lua_State *from, int nargs,
> >                           int *nresults);
> >
> >
> > Do you have any idea, how I need to rewrite the code, if in old code we use
> > just
> > lua_resume(L, NULL, x) ?
>
> It depends on the context of the code around it. Basically, wherever
> you used lua_gettop(L) before, you want to use nres from the out
> parameter now. For example, if you had this before:
>
> /* set up for the call to lua_resume */
> int status = lua_resume(L, NULL, x);
> /* check status */
> int nres = lua_gettop(L);
> /* do stuff with nres */
>
> Then you'd want to do this now:
>
> /* set up for the call to lua_resume */
> int nres;
> int status = lua_resume(L, NULL, x, &nres);
> /* check status */
> /* do stuff with nres */
>
> Joseph C. Sible
>
>

--
Lubos Uhliarik
Software Engineer - EMEA ENG Developer Experience
RH - Brno - TPB-C - 1D221
IRC: zero_byte at irc.freenode.net

RED HAT | TRIED. TESTED. TRUSTED.
Every airline in the Fortune 500 relies on Red Hat.
Find out why at http://www.redhat.com/en/about/trusted

Red Hat Inc. http://cz.redhat.com
Reply | Threaded
Open this post in threaded view
|

Re: New param in lua_resume in Lua 5.4

Joseph C. Sible
On Thu, Jul 9, 2020 at 5:48 PM Lubos Uhliarik <[hidden email]> wrote:

>
> Hi Joseph,
>
> thanks for your answer! Is it still possible to get nres in the old way?
>
> The problem is, httpd is not possible to build with new Lua 5.4, since in mod_lua
> there are like 5 lua_resume calls. There is already macro:
>
> #define lua_resume(a,b)    lua_resume(a, NULL, b)
>
> Is there any chance, to solve this issue only by using macro? Something like:
>
> #if LUA_VERSION_NUM > 503
> #define lua_resume(a,b)    lua_resume(a, NULL, b, NULL)
> #else
> #define lua_resume(a,b)    lua_resume(a, NULL, b)
> #endif
>
>
> lua_gettop(L) is in the code used like 7 times and it is far away from lua_resume
> function calls, so I suppose it won't be so easy to rewrite it, if lua_gettop can NOT
> be used anymore. Or is it possible to use lua_gettop like in version 5.3 and pass NULL to the
> fourth param, as I mentioned above?

You can't pass NULL since it's unconditionally written to, but you can
pass the address of a dummy int instead. If you're okay with using a
GNU extension, you can use a statement expression to do that easily,
like this:

#define lua_resume(a,b) ({int nres; lua_resume(a, NULL, b, &nres); })

By the way, I'm slightly concerned that mod_lua always ignores the
stack after calling lua_resume, but that new #define is no worse than
the code that it was using before for Lua 5.3 and below.

Joseph C. Sible
Reply | Threaded
Open this post in threaded view
|

Re: New param in lua_resume in Lua 5.4

Andrew Gierth
In reply to this post by Lubos Uhliarik
>>>>> "Lubos" == Lubos Uhliarik <[hidden email]> 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.