[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: use of invalid L in libevent wrapper from Lua Programming Gems
- From: Sam Roberts <vieuxtech@...>
- Date: Sat, 19 Dec 2009 10:50:26 -0800
On Sat, Dec 19, 2009 at 3:28 AM, Wim Couwenberg
<wim.couwenberg@gmail.com> wrote:
>> The wrapper in gem 27 doesn't use L as passed to priv.dispatch(),
>> instead it uses some previously-valid L.
>
> You are right. That code implicitly assumes that all events are
> created on the state L that calls Event.dispatch() later on. The
> cause is this line in the handler function in C-Event.c:
>
> lua_getfield(ev->L, LUA_ENVIRONINDEX, "handle_event");
>
> Here it is assumed that the Lua call frame of the dispatch function
> uses ev->L. Another approach could be to store the aux table in the
> registry instead of making it the environment of all (private) C
> calls. See these lines in the initialize function in C-Event.c:
I think the problem is simply that ev->L doesn't exist anymore, it can point
to a collected thread/coroutine/child state. No change to how the aux table is
stored will help, when you handler doesn't have a valid L to access.
This patch uses static globals, so isn't thread safe, but since the
libevent event_dispatch() API isn't thread-safe either, that shouldn't
be a problem.
Btw, not tested!
% svn diff
Index: C-Event.c
===================================================================
--- C-Event.c (revision 710)
+++ C-Event.c (working copy)
@@ -31,21 +31,24 @@
/* event wrapper to pack into userdata */
struct levent {
struct event event;
- lua_State *L;
+ lua_State **L;
};
/* The libevent callback handler */
static void handler(int fd, short event_type, void *arg) {
struct levent *ev = (struct levent *)arg;
- lua_getfield(ev->L, LUA_ENVIRONINDEX, "handle_event");
- lua_pushlightuserdata(ev->L, ev);
- lua_pushnumber(ev->L, fd);
- lua_pushnumber(ev->L, event_type);
- lua_call(ev->L, 3, 0);
+ lua_getfield(*ev->L, LUA_ENVIRONINDEX, "handle_event");
+ lua_pushlightuserdata(*ev->L, ev);
+ lua_pushnumber(*ev->L, fd);
+ lua_pushnumber(*ev->L, event_type);
+ lua_call(*ev->L, 3, 0);
}
+static lua_State* gL;
+
/* bind the lua dispatch function to the libevent dispatch function */
static int dispatch(lua_State *L) {
+ gL = L;
event_dispatch();
return 0;
}
@@ -58,7 +61,7 @@
/* pack levent structure in userdata */
struct levent *ev = (struct levent *)lua_newuserdata(L, sizeof(*ev));
- ev->L = L;
+ ev->L = &gL;
event_set(&ev->event, fd, event_type, handler, ev);
/* set userdata metatable (from aux table) */
Cheers,
Sam