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 Soni L. once stated:
> 
> The same way you'd do it in Lua: Your module table. Or the metatable.

  I went through my existing modules to see if I could forgo the use of the
registry table.  So maybe you can help me.  One problematic module:

	local signal = require "org.conman.signal" -- [1]

	signal.catch('interrupt',function() 
	  print "You can't interrupt me! Muahahahaha!"
	end)

  Seems simple to use, but we need to save a reference to the passed in
function because, as in this example, it can be an anonymous function not
otherwise anchored into memory.  Second, there are some 30+ signals we can
capture (keep that in mind).  Third, our signal handler:

	static void signal_handler(int sig)
	{
	 ...

  Okay.  No context other than the signal that was just generated.  This
means we need to cache the lua_State in a variable visible to our signal
handler.  That can be done during the luaopen() call, so now we have:

	static lua_State *m_L;
	static void signal_handler(int sig)
	{
	 ...

  We're running in a signal handler.  There is not much you can do *safely*
from a signal handler (because you could be in the middle of allocating
memory, in the middle of a Lua call, halfway through manipulating a linked
list, any number of half-finished states exist), and the *only* thing you
can safely call in Lua is lua_sethook().  Even trying to write the signal
number to a table is unsafe.  So we have:

	static lua_State *m_L;
	static volatile sig_atomic_t m_sig;
	static void signal_handler(int sig)
	{
	  m_sig = sig;
	  lua_sethook(m_L,hook_handler,LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT,1);
	}

  We now resume from the signal, and when it's safe for Lua to do so, our
hook_handler() gets called:

	static void hook_handler(lua_State *L,lua_Debug *ar)
	{
	 ...
	}

  Okay, where's our function to handle the signal?  What meta table? 
Where's the module table?  I could try looking for
"package.loaded['org.conman.syslog']" but I can't rely upon that if the
global environment has been sandboxed (the global environment might have
'signal' already loaded, but not 'package' or 'require').  I don't want to
pollute the global environment.  But I have no context to save or retrieve
which function to run.

  Do you have any alternatives that don't rely upon package.loaded[]? 
Because I have no ideas ...

  -spc

[1]	https://github.com/spc476/lua-conmanorg/blob/master/src/signal.c