Search code examples
cgstreamerglibzeromq

Why am I segfault'ing when replacing poll() with zmq_poll() in glib main context?


I'm attempting to integrate zeromq into a glib main loop, but I can't figure out why my program is segfault'ing.

Here's the function that guarantees a segfault after also running g_main_loop_run(loop):

/** set poll fn to operate on zmq or unix sockets */
g_main_context_set_poll_func( g_context, (GPollFunc) zmq_poll );

I thought this would work, considering that zmq_poll shares the same structure as poll, and calling this same function with s/zmq_poll/poll/ works fine.

Stripped version of my code with it still segfault'ing: http://paste.pocoo.org/show/568289/.

(untested) Full version: http://paste.pocoo.org/show/568292/.

Stacktrace:

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff6a2bd50 in ?? ()
   from /usr/lib/libzmq.so.1
(gdb) bt
#0  0x00007ffff6a2bd50 in ?? ()
   from /usr/lib/libzmq.so.1
#1  0x00007ffff6a34b4d in zmq_getsockopt ()
   from /usr/lib/libzmq.so.1
#2  0x00007ffff6a34e1b in zmq_poll ()
   from /usr/lib/libzmq.so.1
#3  0x00007ffff6c89dc8 in ?? ()
   from /usr/lib/libglib-2.0.so.0
#4  0x00007ffff6c8a5f2 in g_main_loop_run ()
  from /usr/lib/libglib-2.0.so.0
#5  0x0000000000402978 in main (argc=1, 
argv=0x7fffffffe5e8) at server.c:229

Compile the code (assuming you have gstreamer and zeromq installed) with:

gcc --debug `pkg-config gstreamer-0.10 --libs` -lzmq `pkg-config gstreamer-0.10 --cflags` -o test test.c

What am I doing wrong?

Any and all help is appreciated, thanks.

EDIT: Got it to work with what alexander suggested by using this function as my poll replacement:

gint zmq_poll_adapter(GPollFD *ufds, guint nfsd, gint timeout_)
{
    zmq_pollitem_t ufds0[nfsd];
    int i;
    for (i = 0; i < nfsd; i++)
    {
        ufds0[i].socket = NULL;
        ufds0[i].fd = ufds[i].fd;
        ufds0[i].events = ufds[i].events;
        ufds0[i].revents = ufds[i].revents;
    }
    zmq_poll(ufds0, nfsd, timeout_);
}

To be honest I'm not even sure how this worked as well as it did, but I'm a C newbie and have little idea how to make a more adaptive adapt().


Solution

  • Expected data format for GPollFunc callback is

    struct GPollFD {
    #if defined (G_OS_WIN32) && GLIB_SIZEOF_VOID_P == 8
      gint64 fd;
    #else
      gint      fd;
    #endif
      gushort   events;
      gushort   revents;
    };
    

    Expected data format for zmq_poll is

    typedef struct
    {
        void //*socket//;
        int //fd//;
        short //events//;
        short //revents//;
    } zmq_pollitem_t;
    

    The solution is to write adapter and pass it to g_main_context_set_poll_func:

    gint zmq_poll_adapter(GPollFD *ufds, guint nfsd, gint timeout_)
    {
        zmq_pollitem_t *ufds0 = adapt(ufds, nfsd);
        zmq_poll(ufds0, nfsd, timeout_);
    }