[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Bug: non-error unwind of previously yielded pcall doesn't restore errfunc.
- From: Alexander Gavrilov <angavrilov@...>
- Date: Mon, 18 Jun 2012 12:29:24 +0400
Hi,
I've noticed one more bug with pcalls in coroutines: they don't
always restore the previous value of errfunc on exit. Specifically,
if a yield happens through a chain of pcalls, and then no errors
are thrown after resume, the errfunc value will remain the same as
at the time of yield.
Example:
function errfunc(x)
return 'errfunc'
end
function test(do_yield)
print('yielding:',do_yield)
pcall(function() -- this pcall sets errfunc back to none
if do_yield then
coroutine.yield() -- stops errfunc from being restored
end
end)
error('fail!')
end
coro = coroutine.wrap(function()
print(xpcall(test, errfunc, false))
print(xpcall(test, errfunc, true))
print(xpcall(test, errfunc, false))
end)
coro()
coro()
Output:
yielding: false
false errfunc
yielding: true
false input:13: fail!
yielding: false
false errfunc
This appears to fix it:
@@ -402,6 +402,9 @@ static void finishCcall (lua_State *L) {
int n;
lua_assert(ci->u.c.k != NULL); /* must have a continuation */
lua_assert(L->nny == 0);
+ /* finish 'lua_pcallk' */
+ if (ci->callstatus & CIST_YPCALL)
+ L->errfunc = ci->u.c.old_errfunc;
/* finish 'lua_callk' */
adjustresults(L, ci->nresults);
/* call continuation function */
Alexander