Search code examples
clinuxglib

g_source_set_callback : invalid callback data pointer


using Glib, I created two GSource and registered the same callback function.

and, pass different data pointers to each GSource.

code is below...

gboolean cb (gpointer data)
{
    printf("data is %d \n", GPOINTER_TO_INT(data));
}

void init_g_source (void)
{
    GSource* src1 = g_timeout_source_new (1000);
    g_source_set_callback (src1, cb, GINT_TO_POINTER(9), NULL);
    g_source_attach (src1, g_main_loop_get_context(mainloop));            
    g_source_unref (src1);

    GIOChannel *ch = g_io_channel_unix_new (socket_fd);        
    GSource* src2 = g_io_create_watch (ch, G_IO_IN);    
    g_source_set_callback (src2, cb, GINT_TO_POINTER(7), NULL);
    g_source_attach (src2, g_main_loop_get_context(mainloop));            
    g_source_unref (src2);  
}

Expected results

  • when src1 callback : data is 9
  • when src2 callback : data is 7

However, actual results

  • when src1 callback : data is 9
  • when src2 callback : data is 6811792

Why is the wrong data pointer only in src2 using socket_fd?

  1. Passed a pointer to a local or global variable : result is the same.

  2. Passed a pointer to memory allocation (g_malloc or g_new) : result is the same.

  3. Passed a NULL pointer : Only the values are different, but the result is the same.


Solution

  • The GSource created by g_io_create_watch() runs callback functions of type GIOFunc, not GSourceFunc. (This is explained in the documentation for g_io_add_watch(), but not mentioned in the documentation for g_io_create_watch().)

    You need different callback functions for the two GSources:

    gboolean cb (gpointer data)
    {
        printf("data is %d \n", GPOINTER_TO_INT(data));
    }
    
    gboolean cb_io (GIOChannel *source, GIOCondition condition, gpointer data)
    {
        printf("data is %d \n", GPOINTER_TO_INT(data));
    }
    
    void init_g_source (void)
    {
        GSource* src1 = g_timeout_source_new (1000);
        g_source_set_callback (src1, cb, GINT_TO_POINTER(9), NULL);
        g_source_attach (src1, g_main_loop_get_context(mainloop));            
        g_source_unref (src1);
    
        GIOChannel *ch = g_io_channel_unix_new (socket_fd);        
        GSource* src2 = g_io_create_watch (ch, G_IO_IN);    
        g_source_set_callback (src2, G_SOURCE_FUNC (cb_io), GINT_TO_POINTER(7), NULL);
        g_source_attach (src2, g_main_loop_get_context(mainloop));            
        g_source_unref (src2);  
    }