[zeromq-dev] Bug? xrep (router) socket asserts on reconnect

Bott, Andrew (TI) Andrew.Bott2 at riotinto.com
Mon Apr 2 08:56:39 CEST 2012


I wanted to flag the following issue:

Platform: win64 / debug, using visual studio 2010 compiler
Language: C++
ZMQ version: 3.1.0

Description:

A router socket and dealer socket, in separate apps, enjoy a good TCP connection and are sending/receiving messages directly. The messages being sent from the dealer to the router do not have an empty first frame.

The application using the router socket is killed, then brought back up.

An assertion is generated (in std lib xtree).

When the dealer sends msgs with an empty first-frame this problem does not occur.

It appears that during a reconnection, the ROUTER socket relies on there being an empty frame. Further anecdotal evidence of this comes from the fact that when the dealer socket is configured to send every message with an empty-frame, recv()s is done on the router socket fail to provide an empty frame for the first message received after a reconnection with the dealer.

It may be that empty frames are mandated when communicating directly to a ROUTER socket. If this is the case can this please be documented.

Another interesting quirk:

In this dealer reconnecting with router scenario, the dealer would usually receive one unexpected message with a single empty frame from the router after a reconnection.

Example code:

This is experimental code I wrote to try reproducing and debugging the assertion. By passing in the 'server' command line arg it will run as a server, with router socket, if 'client' argument then as a client with a dealer

#include <zmq.hpp>
#include <string>
#include <memory>
#include <iostream>

int main(int argc, char ** argv)
{
    if (argc >= 2)
    {
        zmq::context_t context(1);
        if (strcmp(argv[1], "server") == 0)
        {
            zmq::socket_t serverSock(context, ZMQ_XREP);
            serverSock.bind("tcp://*:6010");

            // record the uuid at first contact (a hack admittedly - hope the client never restarts)
            zmq::message_t message;
            serverSock.recv( &message, 0 );
            std::string client_uuid ( static_cast<char*>( message.data()), message.size() );

            int msg_count = 0;
            while (1)
            {
                // print out any message we received as a string
                zmq::message_t recvdMsg;
                serverSock.recv( & recvdMsg, 0 );
                std::string msg ( static_cast<char*>( recvdMsg.data()),recvdMsg.size() );
                std::cout << "Recv: " << msg << std::endl;

                // for every three frames received, send a reply
                msg_count++;
                if (msg_count % 3 == 0)
                {
                                // send uuid frame
                                zmq::message_t msgToSnd(client_uuid.size()) ;
                    memcpy(msgToSnd.data(),client_uuid.data(),client_uuid.size());
                    serverSock.send(msgToSnd, ZMQ_SNDMORE);

                    // send reply body
                    std::string body("hello");
                                zmq::message_t msgToSnd2(body.size()) ;
                    memcpy(msgToSnd2.data(),body.data(),body.size());
                    serverSock.send(msgToSnd2, 0);
                }
            }
        }
        else if (strcmp(argv[1], "client") == 0)
        {
            zmq::socket_t clientSock(context, ZMQ_XREQ);
            clientSock.connect("tcp://localhost:6010");
            while (1)
            {
                Sleep(1000);

                /* Uncomment this block to make it is so server can reconnect without an assert failing

                // Send an empty frame
                zmq::message_t emptyMsg;
                clientSock.send(emptyMsg, ZMQ_SNDMORE);

                */

                //Send request body
                std::string request("Hello!");
                zmq::message_t msgToSnd(request.size()) ;
                memcpy(msgToSnd.data(),request.data(),request.size());
                clientSock.send(msgToSnd, 0);

                //Check if we've received any replies
                zmq::message_t recvdMsg;
                if (clientSock.recv( & recvdMsg, ZMQ_DONTWAIT ))
                {
                    std::string msg ( static_cast<char*>( recvdMsg.data()),recvdMsg.size() );
                    std::cout << "Recv: " << msg << std::endl;
                }
            }
        }
    }
}

Kind regards,

Andrew Bott
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.zeromq.org/pipermail/zeromq-dev/attachments/20120402/b827ca8a/attachment.htm>


More information about the zeromq-dev mailing list