lua-users home
lua-l archive

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


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