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

Pieter Hintjens ph at imatix.com
Mon Apr 2 11:44:21 CEST 2012


Andrew,

Would you check the issue tracker, that this is not already logged,
and if not then create a new issue and attach your test case? Ideally,
write a test case in pure C using only the low-level libzmq API (that
makes sure we exclude any language or platform dependencies).

If you need any help just shout.

Thanks
Pieter

On Mon, Apr 2, 2012 at 1:56 AM, Bott, Andrew (TI)
<Andrew.Bott2 at riotinto.com> wrote:
> 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
>
>
> _______________________________________________
> zeromq-dev mailing list
> zeromq-dev at lists.zeromq.org
> http://lists.zeromq.org/mailman/listinfo/zeromq-dev
>



More information about the zeromq-dev mailing list