lua-users home
lua-l archive

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


Hi,

I wonder if the mail below perhaps went unnoticed - there was
a lot of other mail on the same day :)


So that this mail contains some useful content too, here are two
things that I have found to be very simple to do when accessing
internals, but difficult to reproduce via the current C API:

1) Determine if two threads belong to the same shared interpreter state:

   bool is_same_state(lua_State *L1, lua_State *L2) { return L1->l_G == L2->l_G; }

   I used this for some assertions. I believe the only way around it
   involves using the registry, and thus writing to the stack of at
   least one of the states. This way is purely symmetrical, read-only
   and fast.

2) Determine if the current state is yieldable:

   bool is_yieldable(lua_State *L) { return L->nny == 0; }

   In lua code for 5.2 this can be easily worked around by doing
   pcall(coroutine.yield), but reproducing it in C is rather cumbersome.
   I wanted this to provide a fallback to a non-yielding blocking
   implementation.

Alexander


On Monday 18 June 2012 12:29:24 Alexander Gavrilov wrote:
> 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
>