Windows g_socket_create_source problem



Hi everyone.

I am having some trouble combining Lua Sockets with GTK+. I'm interested in integrating waiting for socket events in the main event loop, which means using a GSocket-type GSource.

I think I am on the right track: I'm creating a Lua Socket, getting the file descriptor (which is a normal fd/SOCKET), create a new GSocket using g_socket_create_source, and attaching a callback that should fire on data available on the socket.

The problem is that once the callback fires (i.e., when I send something to the socket), it keeps on firing like craaayzaay, even if no data is present on the socket. This means that the second time the callback is called, the blocking socket will block the main thread. If I return FALSE instead of TRUE from the callback, the first event is received correctly, the gsource is cleaned up, but of course no other events will be received after that.

Am I missing something or have I hit some winsock-related bug? This is my first foray into GTK+/GLib territory, so one might never know :)

I'm using the GTK+ Windows binaries found at gtk.org (GLib 2.22.2).

Thanks,
Daan Nusman



PS. here's some source code. The addSocket function is called from Lua with
the file descriptor of the socket as argument.

//================================================
// GTK+ networking bridge


// data associated with GSource callback
struct LuaSocketData
{
   lua_State* L;       // the lua state that owns the callback function
   int m_CallbackRef;  // this is a reference to a Lua function
};

// destroys the LuaSocketData (assumes lua state still exists..)
static void LuaSocketData_destroy(gpointer data)
{
   LuaSocketData* luaSocket = (LuaSocketData*)data;
   luaL_unref(luaSocket->L, LUA_REGISTRYINDEX, luaSocket->m_CallbackRef);
}


// called when new data (or error) arrives on a Lua Socket.
gboolean __cdecl onLuaSocketReady(GSocket *socket,
GIOCondition condition, gpointer user_data)
{
   LuaSocketData* luaSocket = (LuaSocketData*)user_data;
   lua_State* L = luaSocket->L;

   if(condition == G_IO_IN)
   {
       printf("callback to lref#%d\n", luaSocket->m_CallbackRef);
       lua_getref(L, luaSocket->m_CallbackRef);

       // this calls Lua, which does a recv on the socket.
if(lua_pcall(L, 0, 0, 0)) {
           printf("callback error: %s\n", lua_tostring(L, -1));
           lua_pop(L, 1);
       }
   }
   else
   {
       __asm int 3 //DebugBreak();  TODO
   }

   return TRUE;   // continue receiving events
}


/*
Lua function that inserts a socket into the GTK+ event loop.

Lua params:
   - 1) socket fd  (use mySocket:getfd())
- 2) callback function, to be called when new data is available on the socket
*/
static int addSocket(lua_State* L)
{
   int sockFD = luaL_checkint(L, 1);

   // what condition to call the callback on
GIOCondition condition = G_IO_IN;
   // create new socket from the lua socket/fd
   GError* err = 0;
   GSocket* gSock = g_socket_new_from_fd(sockFD, &err);
   if(err) luaL_error(L, "%s", err->message);  // fixme: memleak

   // Insert notifications into message loop,
   // with special user data remembering the callback.
   GSource* socketMessageSource =
       g_socket_create_source(gSock, condition, NULL);
   LuaSocketData* luasocketdata =
       (LuaSocketData*)g_malloc(sizeof(LuaSocketData));
lua_pushvalue(L, 2); luasocketdata->m_CallbackRef =
       luaL_ref(L, LUA_REGISTRYINDEX); // store function
   luasocketdata->L = lua_getmainthreadstate(L);

   g_source_set_callback (socketMessageSource,
       (GSourceFunc) onLuaSocketReady,
       luasocketdata, g_free);
g_source_attach (socketMessageSource, NULL); // add source to "main context"
   g_source_unref (socketMessageSource);

   return 0;
}






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