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 William Ahern once stated:
> On Mon, Aug 11, 2014 at 09:08:28PM -0400, Sean Conner wrote:
> <snip>
> >   Not directly, but you can still gain control via a signal handler.  Some
> > basic code:
> <snip>
> >       volatile int          ghookcount;
> >       volatile int          ghookmask;
> >       volatile lua_Hook     ghook;
> >       volatile_sig_atomic_t gsig;
> <snip>
> > 	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 can't be async-signal-safe unless all other signals are blocked during
> execution of the handler. So there should be the caveat that when installing
> the signal handler, sigfillset is used to initialize sa_mask.

  This is the best you can do with ANSI-C signal semantics if you want to
gain control with a signal handler.

  And yes, the way I do this under POSIX is technically a race condition
(two signals at the same time).  

  The previous version of signal handling I did, the code looked like:

	volatile sig_atomic_t gsig;
	volatile sig_atomic_t gsigs[NSIG];

	void signal_handler(int sig)
	{
	  gsig = 1;
	  gsigs[sig] = 1;
	}

and it was up to the rest of the code to check gsig and the appropriate
gsigs[] entry.  If you want portable and safe, that's it.  

> >   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:
> 
> The safest way is to not handle signals asynchronously at all. 

  "The safest way is to not handle signals ------------- at all."

  Fixed that for you 8-P

> But the problem with sigtimedwait is that you often want some sort of
> concurrent execution of signal handlers without having to explicitly query
> them. My cqueues library provides an API for kernel-based, event-oriented
> signal management. Internally it uses signalfd on Linux and kqueue
> EVFILT_SIGNAL on BSDs (including OS X). 

  I must be running a Linux kernel older than 20 minutes because I don't
have signalfd on my system. [1]

> On systems like Solaris it queries
> sigtimedwait on a timer. The following example will work on all those
> systems:
> 
> 	local signal = require"cqueues.signal"
> 	local sigfd = signal.listen(signal.SIGTERM, signal.SIGINT)
> 
> 	while true do
> 		local signo = sigfd:wait() -- doesn't block process
> 
> 		print(signo)
> 	end

  But this won't handle the original problem:

	coroutine.resume(coroutine.create(function() while true do end end))

  -spc (thinks signals was one of the poorer thought out concepts of Unix)

[1]	Not everybody updates their systems every ten minutes.  I don't do
	that, because I operate under the "if it ain't broke, don't fix it"
	mandate.  And because of that, I wasn't affected by Heartbleed.  Nor
	have I been bitten by updates borking my system.