lua-users home
lua-l archive

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


It was thus said that the Great Jay Carlson once stated:
> On Aug 11, 2014 7:54 PM, "Sean Conner" <sean@conman.org> wrote:
> >
> > It was thus said that the Great Jay Carlson once stated:
> > > On Aug 11, 2014 1:48 PM, "Thiago L." <fakedme@gmail.com> wrote:
> > >
> > > > On 11/08/14 02:34 PM, Jay Carlson wrote:
> > >
> > > >> Why do people like MediaWiki disable coroutines, anyway?
> > > >
> > > > Because you can't interrupt running coroutines?
> > > >
> > > > coroutine.resume(coroutine.create(function() while true do end end))
> --
> > > good luck interrupting me
> > >
> > > OK, that's a good reason. (OTOH, if you were going to tear down the
> runtime
> > > in response to an interrupt I'm not sure it matters.)
> > >
> > > You can navigate from a lua_State to its global state, but you can't
> > > navigate from the global state to the current thread. I'm not certain
> what
> > > "current thread" really means anyway.
> >
> >   Um ... lua_pushthread()?
> 
> In a signal handler? All you have is the handle to the L you created.

  Not directly, but you can still gain control via a signal handler.  Some
basic code:

	/*-------------------------------------------------------------
	; the following are marked volatile because they're changed from
	; outside the normal flow of control.  This ensures that the C
	; compiler will always read these values and not cache it
	; temporarily during an expression.
	;--------------------------------------------------------------*/
	
	volatile int          ghookcount;
	volatile int          ghookmask;
	volatile lua_Hook     ghook;	
	volatile_sig_atomic_t gsig;
	
	/*--------------------------------------------------------------
	; reference to a Lua-written signal handler
	;------------------------------------------------------*/
	
	int gref = LUA_NOREF;
	
	/*-------------------------------------------------------------------
	; grab control from Lua from a debug hook set in a signal handler.
	; We call a user-supplied function, referenced by gref and pass it
	; the signal number.  But techincally, we can a lot here since we're
	; no longer in "signal space" by the time this is called.
	;--------------------------------------------------------------------
	
	void luasigbackend(lua_State *L,lua_Debug *ar)
	{
	  lua_sethook(L,NULL,0,0); /* no hooks for this call */
	  lua_pushinteger(L,gref);
	  lua_gettable(L,LUA_REGISTRYINDEX);
	  lua_pushinteger(L,gsig);
	  if (lua_pcall(L,1,0,0) != 0)
	    lua_error(L);
	  
	  /*---------------------------------------------------------
	  ; and now we resume with our regularly scheduled coroutine
	  ;----------------------------------------------------------*/
	  
	  lua_sethook(L,ghook,ghookmask,ghookcount);
	  gsig = 0;
	}
	  
	/*------------------------------------------------------------
	; signal handler, were we install a debug hook to trap on
	; practically anything the Lua interpreter will do.  lua_sethook()
	; is specifically mentioned as being signal safe, and in checking
	; the code for the lua_gethook*() functions, they, too, are signal
	; safe (through 5.2---I haven't checked the 5.3 code yet).  We call
	; these so that any debug code that might be installed can be
	; restored after we're done.
	;----------------------------------------------------------------*/

	void signal_handler(int sig)
	{
	  if (!gsig)
	  {
	    gsig       = sig;
	    ghookcount = lua_gethookcount(gL);
	    ghookmask  = lua_gethookmask(gL);
	    ghook      = lua_gethook(gL);
	    lua_sethook(gL,luasigbackend,LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT,1);
	  }
	}

	/*-----------------------------------------------------------------
	; This just handles a single signal, just for simplicity.  Usage:
	;	signal(signum,function(sig) ... end)
	;-----------------------------------------------------------------*/
	
	int my_signal_catch(lua_State *L)
	{
	  lua_settop(L,2);
	  signal(lua_checkinteger(L,1),signal_handler);
	  luaL_checktype(L,2,LUA_TFUNCTION);
	  luaL_unref(L,LUA_REGISTRYINDEX,ref);
	  gref = luaL_ref(L,LUA_REGISTRYINDEX);
	  return 0;
	}

  Yeah, it's a bit of a round-about way of doing things, but it appears to
tbe the safest way of handling signals in Lua.  I've done two
implementations based on this method, on for ANSI-C only:

	https://github.com/spc476/lua-conmanorg/blob/master/src/signal-ansi.c
	
and one for POSIX (and supports POSIX signal sets):

	https://github.com/spc476/lua-conmanorg/blob/master/src/signal-posix.c
	
  -spc (The POSIX module contains some additonal calls, but otherwise
	presents the same API as the ANSI version)