lua-users home
lua-l archive

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




On 30/09/15 05:05 PM, Sean Conner wrote:
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:
Use a table as an upvalue.

	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

This is VERY unsafe! You're potentially breaking a sandbox by doing a sethook. And you don't reset it, either. And you're doing it from a separate thread. Use a (light?) userdata and do the polling in Lua. Or just set the hook and have it called nonstop.

(Also how do you deal with multiple states? As far as I know, you can't, unless you use a lightuserdata!)

--
Disclaimer: these emails may be made public at any given time, with or without reason. If you don't agree with this, DO NOT REPLY.