lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On Thu, Mar 17, 2016 at 06:07:51PM -0700, William Ahern wrote:
> On Fri, Mar 18, 2016 at 02:07:11AM +0300, Nagaev Boris wrote:
> > $ cat bug.lua
> > local function yieldFirst(it)
> >     return coroutine.wrap(function()
> >         coroutine.yield(it())
> >     end)
> > end
> > 
> > local text = "1 2 3"
> > local it = text:gmatch("(%d+)")
> > local head = yieldFirst(it)
> > local one = head()
> > print(one)
> > assert(one == '1')
> > 
> > $ ./lua-5.3.1/src/lua bug.lua
> > 1
> > $ ./lua-5.3.2/src/lua bug.lua
> > function: 0x243f820
> > ./lua-5.3.2/src/lua: bug.lua:12: assertion failed!
> > stack traceback:
> >         [C]: in function 'assert'
> >         bug.lua:12: in main chunk
> >         [C]: in ?
> > 
> 
> My first guess is that lstrlib.c:gmatch is storing the lua_State object (see
> prepstate) used when creating the closure. When the closure is invoked, it
> uses this original lua_State instead of the current lua_State invoking the
> closure. But the original lua_State is busy resuming the new lua_State.
> 
> The immediate solution might be to add
> 
> 	gm->ms.L = L
> 

This is probably the correct solution. In Lua 5.2 the initialization of
MatchState happens every time gmatch_aux (the closure) is invoked. It looks
like for 5.3 this was refactored so that MatchState is only initialized
once. But what was forgotten in the process is that lua_State might change
when the closure is invoked.