lua-users home
lua-l archive

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


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