lua-users home
lua-l archive

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


This is going to be rather long...

On 11/04/2011 05:11, Sam Roberts whispered from the shadows...:
> I've followed your requests,  but I don't recall you ever saying
> explicitly what you have "working partially" or what you are trying to
> do, making it hard for anybody to really help (other than the lua
> authors changing how 5.2 works, which isn't very likely).

By partially working I mean that I have managed to set the thread's
global environment so that each thread has its own environment that is
separated from the master state's environment, so that "globals" created
in the thread remain confined to that thread:

static void
lua_thread_newenv(lua_State *L)
{
	lua_newtable(L); 			/* new_G  */
	lua_pushvalue(L, -1);			/* new_G new_G */
	lua_pushliteral(L, "__index");		/* new_G new_G __index */
	lua_pushvalue(L, LUA_GLOBALSINDEX);	/* new_G new_G __index old_G */
	lua_settable(L, -3);			/* new_G new_G */
	lua_setmetatable(L, -2);		/* new_G */
	lua_replace(L, LUA_GLOBALSINDEX);	/* -- */
}

Now the C layer calling Lua call-back functions can force the Lua
function to use the thread's environment for its function environment...

...
	PT_BEGIN(&ctx->lua.pt);

	lua_getglobal(L1, "hook");		/* hook */
	lua_getfield(L1, -1, hook);		/* hook fn */
	lua_remove(L1, -2);			/* fn */

	nargs = (*initfn)(L1, ctx);		/* fn ... */

	if (nargs < 0 || !lua_isfunction(L1, -1 - nargs)) {
		lua_pop(L1, lua_gettop(L1));
		PT_EXIT(&ctx->lua.pt);
	}

	/* Force hook.fn environment to that of the thread. */
	lua_pushvalue(L1, LUA_GLOBALSINDEX);
	(void) lua_setfenv(L1, -2 - nargs);
...

> I'm curious, but so far have no idea what to suggest. What is the
> problem you are trying to solve?

The C layer handles all the network IO events using a my own IO event
library (similar to libev or libevent). The C layer loads the Lua code
_once_ into a master state on startup and then creates threads for each
connection from the master state so as to avoid reloading the scripts
for every client connection; this was the closest thing to a Lua "fork"
or "clone" state that I could find. Also I need threads for yield/resume
ability to handle IO events. So far all good.

So here I have call-back functions written in Lua to be called by C. The
C layer when it creates the thread will provide some extra information
during the course of the client connection via tables placed in the
thread's (global) space, eg "client" containing things like client.ip,
client.hostname, client.sess_id, etc..

So the Lua script can define call-back hooks for those parts of the
protocol its going to handle; not all the call-backs hook need be
defined, eg.

function hook.request(input)
	-- do stuff
end

So far so good. Now the problem...

function hook.request(input)
	local rev_ip = net.reverse_ip(client.ip)
	...
	rc = some_support_function(a,b,c)
	...
end	

function some_support_function(foo,bar,bat)
	...
	if client.ip == "192.0.2.1" then
		return "test net"
	end
	...
end

Now since hook.request has had its environment forced to be the same as
the thread's environment by the C layer, the hook.request function can
access the client table in the thread space without issue. BUT function
calls from within hook.request to supporting application functions will
throw an error when they try to access client table, because the
function call chain does not inherit that of the caller or thread space
in which it executes. This is the essence of my problem.

-- 
Anthony C Howe            Skype: SirWumpus                  SnertSoft
                        Twitter: SirWumpus      BarricadeMX & Milters
http://snert.com/      http://nanozen.info/     http://snertsoft.com/