[zeromq-dev] shutdown mutex issue with 2.10

Oliver Smith oliver at kfs.org
Thu Oct 14 01:49:25 CEST 2010


  Recently upgraded from an earlier 2.x (2.0.7 I think) to 2.1.0. I 
immediately ran into an unusual problem under Linux where my unit test 
module passed all tests but then failed to terminate.

The test unit keeps getting stuck with this backtrace, apparently in the 
destructor for a static zmq::context being destroyed at shutdown.

0xb7fe2430 in __kernel_vsyscall ()
(gdb) bt
#0  0xb7fe2430 in __kernel_vsyscall ()
#1  0xb7da9af9 in __lll_lock_wait () at ../nptl/sysdeps/unix/sysv/linux/i386/i686/../i486/lowlevellock.S:142
#2  0xb7da513b in _L_lock_748 () from /lib/tls/i686/cmov/libpthread.so.0
#3  0xb7da4f61 in __pthread_mutex_lock (mutex=0x806a040) at pthread_mutex_lock.c:61
#4  0xb7f0716a in zmq::ctx_t::terminate() () from /usr/lib/libzmq.so.0
#5  0xb7f22691 in zmq_term () from /usr/lib/libzmq.so.0
#6  0x08059413 in ~context_t (this=0x806a008, __in_chrg=<value optimized out>) at /playnet/wwiiol/include/zmq.hpp:178
#7  0x0805a924 in ~Fnar (this=0x80697dc, __in_chrg=<value optimized out>) at wwii/wwiiZMQ.cpp:12
#8  0xb7c721bf in __run_exit_handlers (status=0, listp=0xb7d99324, run_list_atexit=true) at exit.c:78
#9  0xb7c7222f in *__GI_exit (status=0) at exit.c:100
#10 0x0805714c in main (argc=1, argv=0xbfffee64) at tests/testUnits.cpp:241

You can replicate the issue with the following code:

////////////////////////////////////////////////////////////
// Demonstrates zmq hang on static destructor.

#include<stdio.h>
#include<zmq.hpp>
#include<unistd.h>
#include<stdlib.h>
#include<memory.h>

// Static context: created on startup.
static zmq::context_t staticContext(1) ;

// Wrapper for 'free' for strdup'd message_t.
static void freepayload(void* data, void*)
{
     free(data) ;
}

// Send a text string using strdup to copy the string.
static void send(zmq::socket_t&  socket, const char* const text)
{
     zmq::message_t msg(strdup(text), strlen(text) + 1, freepayload) ;
     socket.send(msg, ZMQ_NOBLOCK) ;
}

// To ensure that the inner zmq::context_t is destroyed well
// before the static one, wrap the code to be tested here.
// This also helps isolate the static context_t as the cause,
// by verifying we were able to leave this function.
void fn()
{
     // locally scoped context to be destroyed when we exit fn().
     zmq::context_t innerContext(1) ;

     // Bind a socket on it.
     zmq::socket_t is(innerContext, ZMQ_PULL) ;
     is.bind("tcp://127.0.0.1:12345") ;

     // verify we can't receive anything.
     zmq::message_t msg ;
     if ( is.recv(&msg, ZMQ_NOBLOCK) )
     {
         printf("error: should not have received from is\n") ;
     }

     // now bind a receiving socket
     // **BINDS TO THE STATIC CONTEXT, NOT LOCAL CONTEXT**
     zmq::socket_t os(staticContext, ZMQ_PUSH) ;
     os.connect("tcp://127.0.0.1:12345") ;

     // send a message between contexts.
     send(os, "hello") ;

     // record that we're leaving this function.
     printf("reaching end of function\n") ;
}

int
main(int argc, const char* const agv[])
{
     printf("calling fn\n") ;

     fn() ;

     printf("returned from fn\n") ;

     exit(0) ;
}





More information about the zeromq-dev mailing list