Re: [zeromq-dev] native select call
Thanks Doron, I indeed found the info on the list. As for anyone else dealing with Python's asyncore module; I've created a simple dispatcher class for your convenience: https://gist.github.com/sphaero/c63bc1a4485d5bbbdd9478db4c1de6b0 Rg, Arnaud On 2016-05-19 18:29, Doron Somech wrote: Someone actually asked about it few weeks ago on the list, try to search. Anyway you can use socket FD but you have to do all the heavy lifting yourself. The ready to receive FD doesnt mean anything to the user, for the library it means the socket received new command need processing. To handle incoming messages you should call recv with NO_BLOCK until EAGAIN. The recv method also handle the incoming command even if no message available. On May 19, 2016 16:52, "Arnaud Loonstra"wrote: This must have been asked many times and I recall working with it before but was it possible to use a normal/native/regular select call on a zmq socket? I know about the edge and level triggering but Im kind of lost. PyZMQ writes a bit about it but only tells to avoid using zmq.FD. http://pyzmq.readthedocs.io/en/latest/eventloop.html [1] Im trying to get a zmq socket into a python asyncore application. Unfortunaltely asyncore uses a native select() (or poll() if it finds it). So either I need to rewrite the asyncore module or I make the socket work with the native select(). Any pointers? Rg, Arnaud ___ zeromq-dev mailing list zeromq-dev@lists.zeromq.org [2] http://lists.zeromq.org/mailman/listinfo/zeromq-dev [3] ___ zeromq-dev mailing list zeromq-dev@lists.zeromq.org http://lists.zeromq.org/mailman/listinfo/zeromq-dev
Re: [zeromq-dev] ZeroMQ STREAM Socket Type
Thanks for the reply. First, I think the diagram below (please forgive my poor ASCII art) shows what I was trying to explain. Original (working code): PUSH (three part message) ---TCP--> PULL (three part message) Currently Planned Implementation: STREAM Client (PUSH replacement)--TCP> Data Link Server -MAGIC?---> Data Link Client--TCP-->STREAM Server (PULL replacement) Each STREAM socket must talk to the data link's TCP service (and this is "regular" TCP) which then forwards the sender's data across the link. No data from the PULL replacement will be able to make it back due to limitations with the physical layer on the data link (labeled "MAGIC?"). I still have a few questions left: 1. Does it matter what I set the ZMQ_CONNECT_RID to? I'm assuming the STREAM Server isn't looking for this. 2. How does the receive side look like? Do I get a identity from the Data Link Client after I bind? Do I read this out each time before I read the actual data? 3. I'm assuming it's best to now NOT use the three part message (have to check each zmq_send() call for the number of bytes sent). Instead, I'm planning on serializing and ensuring that all the bytes make it across. Thanks again for the help. On Tue, May 24, 2016 at 3:00 AM, Doron Somechwrote: > Ok, you have an option called ZMQ_CONNECT_RID, when you set it in a STREAM > socket is set the identity of the first peer, so instead of what you are > doing now, do: > > 1. Set the socket CONNECT RID to "C" (or whatever) > 2. Connect the socket (RID MUST BE BEFORE CONNECT) > 3. Send identity"C" > 4. Send message > > Regarding atomic send, it wont, STREAM will send any bytes arrive, but it > should not matter as TCP is stream protocol snd don't have the notion of > messages. > > Zero length message is not flushing the data, is just closing the tcp > socket. You can also just close the socket. > On May 24, 2016 09:52, "Doron Somech" wrote: > >> It seems what you are doing won't work as currently it is hard to use >> STREAM as the first sender, as you don't know the identity if the peer. I >> think someone added notify option, worth to check it out. Are you using >> STREAM at both sides? >> On May 24, 2016 00:04, "Peter Witkowski" wrote: >> >>> Sorry to spam everyone, but just to clarify, when I say that PUSH-PULL >>> doesn't work because of handshaking, I'm speaking about the ZeroMQ >>> handshake (greetings, etc.). The data link handles the TCP connection >>> stuff. >>> >>> On Mon, May 23, 2016 at 4:58 PM, Peter Witkowski >>> wrote: >>> Hello, Long story short, I have code that works that I now need to refactor. The networking for my application has changed and I need to push my ZeroMQ messages over a half-duplex (i.e., one way) wireless data link. The data link is looking for raw TCP on either end and specifies what side is the client and server. You can think of this data link as a one way bridge, with a TCP endpoint on either end that I need to talk to. The data link then forwards the TCP traffic in some weird protocol to the other side. The code I have written is a PUSH-PULL pattern, which doesn't work due to the handshaking involved at the socket's start-up (I'm assuming there's no way to disable this). The code sends and receives a three-part message (the third message part is large, about 65KB). I need to refactor this into two STREAM sockets, but I'm having problems (conceptually) with sending and receiving. Here's some pseudo code for the sender (which is the client per the data link): - Set-up context, open socket, call connect. - Get ZMQ_IDENTITY using zmq_getsockopt() - Send identity - Send message part 1 (assuming that this is an atomic send and won't only send N bytes) - Send identity - Send message part 2 (see previous assumption about atomic) - Send identity - Send message part 3 (see previous assumption about atomic) - When I'm ready to close, I send the identity followed by a zero length packet The receiver (TCP server per the data link) is basically the opposite, but here I'm a bit confused. Namely, is each receive call atomic, or is there a chance that the data gets chunked up into multiple messages? Also, do I need to read off the identifier each time or does the library only forward the message parts? Also, in general, are there any issues with using ZeroMQ (even STREAM sockets) with this set-up? Note that my assumption is that the receiver never needs to send data and the sender never needs to receive data. Thanks in advance for the help. -- Peter Witkowski pwitkow...@gmail.com >>> >>> >>> >>> -- >>> Peter Witkowski >>>
[zeromq-dev] vector io for TCP sockets
Hi, I have been thinking on how to change the stream_engine_t class to use vector io to save copying the message data into the send buffer. The basic idea is to send the data directly from the messages in the queue. To do this, the headers must be created in an independent array and the lock-free queue needs to provide an iterator to traverse the elements in the queue. I think this should be possible with the current implementation because it is a producer/consumer queue where only one side can remove items, and this is the stream_engine. The other side can only add new elements, and that should not invalidate the iterator (which is probably a pointer to the current element). Every message then uses two io_vec elements, the first pointing to the header data and the second one pointing to the message data. I've tried to write down a pseudo-code implementation of the algorithm: - The write buffer in stream_engine_t is removed. - stream_engine_t gets an array iovecs of IOV_MAX io_vec elements - stream_engine_t gets an array headerbuf of IOV_MAX/2 * 10 bytes to hold the headers - stream_engine_t stores an offset counting the already sent bytes of the first message to be sent When called, out_event will check if the mailbox Q is not empty. If so: char* h = [0]; io_vec* v = [0]; msg = Q.cbegin(); last_msg = Q.cend(); bool firstMessage = true; while (number of processed messages <= IOV_MAX/2 && msg != last_msg) { hlen = create_header_at(h, *msg); // hlen == 2 || hlen == 10 h += hlen; // send header v->iov_base = h; v->iov_len = hlen; v += 1; // send data v->io_base = msg->data() + offset; offset = 0; v->iov_len = msg->size(); v += 1; ++msg; } // v - iovecs is the number of created io_vec elements ssize_t sent = writev(socket, iovecs, (v - iovecs) ); // error checking ... // no pop messages from the queue and check if there is a remainder while ( (sent - Q.front().size() > 0) { msg_t msg = Q.pop(); sent -= msg.size(); } if (sent >= 0) { offset = sent; } It looks reasonable to me, but I am not sure about the implications, especially when considering different message sizes. For very small messages, this will probably be slower than the original stream_engine. IOV_MAX is 1024 on my Linux machine, so for one-byte messages this would send 512 bytes of message data with one syscall, compared to 8192/3=2730 messages with the old implementation. There should be a message size where it will get faster, but I have not much experience with vector io to guess anything. Maybe somebody could provide some feedback? Best wishes, Jens -- Dr. Jens Auer | CGI | Software Engineer CGI Deutschland Ltd. & Co. KG Rheinstraße 95 | 64295 Darmstadt | Germany T: +49 6151 36860 154 jens.a...@cgi.com Unsere Pflichtangaben gemäß § 35a GmbHG / §§ 161, 125a HGB finden Sie unter de.cgi.com/pflichtangaben. CONFIDENTIALITY NOTICE: Proprietary/Confidential information belonging to CGI Group Inc. and its affiliates may be contained in this message. If you are not a recipient indicated or intended in this message (or responsible for delivery of this message to such person), or you think for any reason that this message may have been addressed to you in error, you may not use or copy or deliver this message to anyone else. In such case, you should destroy this message and are asked to notify the sender by reply e-mail. ___ zeromq-dev mailing list zeromq-dev@lists.zeromq.org http://lists.zeromq.org/mailman/listinfo/zeromq-dev
Re: [zeromq-dev] ZeroMQ 4.2 release, planning
Done! With latest czmq travis script it is now possible to test the JNI bindings and when tagging[1] deploying the android jar file automatically as its done with the autotools tarballs :) [1] https://github.com/zeromq/czmq/releases/tag/v3.0.3-testing 2016-05-10 23:58 GMT+02:00 Luca Boccassi: > On Tue, 2016-05-10 at 13:05 +0200, Kevin Sapper wrote: > > I just pushed changes to zproject and czmq to enable > > automatic travis github releases as well. There is a > > czmq test release that shows that it's working: > > > > https://github.com/zeromq/czmq/releases/tag/v3.0.3-testing > > Awesome, thanks! > > One fix we need to do (I can send a PR tomorrow if no one else beats me > to it) is that the CMake stuff is not included in EXTRA_DIST, so it's > missing from the release tarball. > > > 2016-05-10 5:16 GMT+02:00 Pieter Hintjens : > > > > > Kevin, this is really neat. :) > > > > > > On Mon, May 9, 2016 at 11:26 PM, Ewen McNeill > > > wrote: > > > > On 9/05/16 21:45, Kevin Sapper wrote: > > > >> > > > >> [1] https://github.com/zeromq/libzmq/releases/tag/v4.0.2-test > > > > > > > > > > > > Thanks for automating this. It looks great. > > > > > > > > This gives us two downloads per release (each in .tar.gz and .zip): > > > > > > > > > > > > https://github.com/zeromq/libzmq/releases/download/v4.0.2-test/zeromq-4.2.0.tar.gz > > > > -- the Travis generated tarball (which I assume is prepared ready for > > > > "./configure, make, make install") > > > > > > > > https://github.com/zeromq/libzmq/archive/v4.0.2-test.tar.gz > > > > -- the GitHub auto-generated tarball from that release tag (which I > > > assume > > > > is what a git clone would give you, so a few extra steps required). > > > > > > > > So downloaders can choose the one they want. (Including .zip file > > > > variations of both.) > > > > > > > > Also of note, both URLs include a filename at the end, so "wget" > > > > automatically does the right thing with the downloaded files (I just > > > > tested). > > > > > > > > Ewen > > > > > > > > ___ > > > > zeromq-dev mailing list > > > > zeromq-dev@lists.zeromq.org > > > > http://lists.zeromq.org/mailman/listinfo/zeromq-dev > > > ___ > > > zeromq-dev mailing list > > > zeromq-dev@lists.zeromq.org > > > http://lists.zeromq.org/mailman/listinfo/zeromq-dev > > > > > ___ > > zeromq-dev mailing list > > zeromq-dev@lists.zeromq.org > > http://lists.zeromq.org/mailman/listinfo/zeromq-dev > > > > ___ > zeromq-dev mailing list > zeromq-dev@lists.zeromq.org > http://lists.zeromq.org/mailman/listinfo/zeromq-dev > ___ zeromq-dev mailing list zeromq-dev@lists.zeromq.org http://lists.zeromq.org/mailman/listinfo/zeromq-dev
Re: [zeromq-dev] ZeroMQ STREAM Socket Type
Ok, you have an option called ZMQ_CONNECT_RID, when you set it in a STREAM socket is set the identity of the first peer, so instead of what you are doing now, do: 1. Set the socket CONNECT RID to "C" (or whatever) 2. Connect the socket (RID MUST BE BEFORE CONNECT) 3. Send identity"C" 4. Send message Regarding atomic send, it wont, STREAM will send any bytes arrive, but it should not matter as TCP is stream protocol snd don't have the notion of messages. Zero length message is not flushing the data, is just closing the tcp socket. You can also just close the socket. On May 24, 2016 09:52, "Doron Somech"wrote: > It seems what you are doing won't work as currently it is hard to use > STREAM as the first sender, as you don't know the identity if the peer. I > think someone added notify option, worth to check it out. Are you using > STREAM at both sides? > On May 24, 2016 00:04, "Peter Witkowski" wrote: > >> Sorry to spam everyone, but just to clarify, when I say that PUSH-PULL >> doesn't work because of handshaking, I'm speaking about the ZeroMQ >> handshake (greetings, etc.). The data link handles the TCP connection >> stuff. >> >> On Mon, May 23, 2016 at 4:58 PM, Peter Witkowski >> wrote: >> >>> Hello, >>> >>> Long story short, I have code that works that I now need to refactor. >>> The networking for my application has changed and I need to push my ZeroMQ >>> messages over a half-duplex (i.e., one way) wireless data link. The data >>> link is looking for raw TCP on either end and specifies what side is the >>> client and server. You can think of this data link as a one way bridge, >>> with a TCP endpoint on either end that I need to talk to. The data link >>> then forwards the TCP traffic in some weird protocol to the other side. >>> >>> The code I have written is a PUSH-PULL pattern, which doesn't work due >>> to the handshaking involved at the socket's start-up (I'm assuming there's >>> no way to disable this). The code sends and receives a three-part message >>> (the third message part is large, about 65KB). I need to refactor this >>> into two STREAM sockets, but I'm having problems (conceptually) with >>> sending and receiving. >>> >>> Here's some pseudo code for the sender (which is the client per the data >>> link): >>> >>>- Set-up context, open socket, call connect. >>>- Get ZMQ_IDENTITY using zmq_getsockopt() >>>- Send identity >>>- Send message part 1 (assuming that this is an atomic send and >>>won't only send N bytes) >>>- Send identity >>>- Send message part 2 (see previous assumption about atomic) >>>- Send identity >>>- Send message part 3 (see previous assumption about atomic) >>>- When I'm ready to close, I send the identity followed by a zero >>>length packet >>> >>> The receiver (TCP server per the data link) is basically the opposite, >>> but here I'm a bit confused. Namely, is each receive call atomic, or is >>> there a chance that the data gets chunked up into multiple messages? Also, >>> do I need to read off the identifier each time or does the library only >>> forward the message parts? >>> >>> Also, in general, are there any issues with using ZeroMQ (even STREAM >>> sockets) with this set-up? Note that my assumption is that the receiver >>> never needs to send data and the sender never needs to receive data. >>> >>> Thanks in advance for the help. >>> -- >>> Peter Witkowski >>> pwitkow...@gmail.com >>> >> >> >> >> -- >> Peter Witkowski >> pwitkow...@gmail.com >> >> ___ >> zeromq-dev mailing list >> zeromq-dev@lists.zeromq.org >> http://lists.zeromq.org/mailman/listinfo/zeromq-dev >> > ___ zeromq-dev mailing list zeromq-dev@lists.zeromq.org http://lists.zeromq.org/mailman/listinfo/zeromq-dev
Re: [zeromq-dev] ZeroMQ STREAM Socket Type
It seems what you are doing won't work as currently it is hard to use STREAM as the first sender, as you don't know the identity if the peer. I think someone added notify option, worth to check it out. Are you using STREAM at both sides? On May 24, 2016 00:04, "Peter Witkowski"wrote: > Sorry to spam everyone, but just to clarify, when I say that PUSH-PULL > doesn't work because of handshaking, I'm speaking about the ZeroMQ > handshake (greetings, etc.). The data link handles the TCP connection > stuff. > > On Mon, May 23, 2016 at 4:58 PM, Peter Witkowski > wrote: > >> Hello, >> >> Long story short, I have code that works that I now need to refactor. >> The networking for my application has changed and I need to push my ZeroMQ >> messages over a half-duplex (i.e., one way) wireless data link. The data >> link is looking for raw TCP on either end and specifies what side is the >> client and server. You can think of this data link as a one way bridge, >> with a TCP endpoint on either end that I need to talk to. The data link >> then forwards the TCP traffic in some weird protocol to the other side. >> >> The code I have written is a PUSH-PULL pattern, which doesn't work due to >> the handshaking involved at the socket's start-up (I'm assuming there's no >> way to disable this). The code sends and receives a three-part message >> (the third message part is large, about 65KB). I need to refactor this >> into two STREAM sockets, but I'm having problems (conceptually) with >> sending and receiving. >> >> Here's some pseudo code for the sender (which is the client per the data >> link): >> >>- Set-up context, open socket, call connect. >>- Get ZMQ_IDENTITY using zmq_getsockopt() >>- Send identity >>- Send message part 1 (assuming that this is an atomic send and won't >>only send N bytes) >>- Send identity >>- Send message part 2 (see previous assumption about atomic) >>- Send identity >>- Send message part 3 (see previous assumption about atomic) >>- When I'm ready to close, I send the identity followed by a zero >>length packet >> >> The receiver (TCP server per the data link) is basically the opposite, >> but here I'm a bit confused. Namely, is each receive call atomic, or is >> there a chance that the data gets chunked up into multiple messages? Also, >> do I need to read off the identifier each time or does the library only >> forward the message parts? >> >> Also, in general, are there any issues with using ZeroMQ (even STREAM >> sockets) with this set-up? Note that my assumption is that the receiver >> never needs to send data and the sender never needs to receive data. >> >> Thanks in advance for the help. >> -- >> Peter Witkowski >> pwitkow...@gmail.com >> > > > > -- > Peter Witkowski > pwitkow...@gmail.com > > ___ > zeromq-dev mailing list > zeromq-dev@lists.zeromq.org > http://lists.zeromq.org/mailman/listinfo/zeromq-dev > ___ zeromq-dev mailing list zeromq-dev@lists.zeromq.org http://lists.zeromq.org/mailman/listinfo/zeromq-dev
Re: [zeromq-dev] What are the “serious caveats” with ZMQ_FD?
Only if you are using thread safe sockets. You can save a call by with just calling with ZMQ_NOBLOCK (no need for ZMQ_EVENTS). Then you don't need to worry about race condition. On May 24, 2016 08:22, "Huttunen, Kalle (GE Healthcare)" < kalle.huttu...@ge.com> wrote: > > after your call to zmq_recv(), but before your call to select() / poll() > > > > Are you talking about the way to receive messages when the ZMQ_FD signals? > Basically I currently have the following code called when the ZMQ_FD > becomes readable (in pseudocode): > > > > while ZMQ_EVENTS has ZMQ_POLLIN bit set > > { > > receive message from socket; > > process message; > > } > > > > Is there a potential race condition here? > > > > Thanks, > > -- > > Kalle Huttunen > > > > *From:* zeromq-dev [mailto:zeromq-dev-boun...@lists.zeromq.org] *On > Behalf Of *Dave Lambley > *Sent:* 23. toukokuuta 2016 19:08 > *To:* ZeroMQ development list > *Subject:* EXT: Re: [zeromq-dev] What are the “serious caveats” with > ZMQ_FD? > > > > On 23 May 2016 at 10:23, Huttunen, Kalle (GE Healthcare) < > kalle.huttu...@ge.com> wrote: > > It seems that sending on the socket makes the ZMQ_FD readable. That in > turn triggers the calling of the code where I check ZMQ_EVENTS and receive > everything from the socket. This way I end up checking ZMQ_EVENTS after > each send. > > Is the ZMQ_FD becoming readable when sending on the socket something that > can be relied on? > > > > I believe you have a race condition. If a message arrives after your call > to zmq_recv(), but before your call to select() / poll(), it will block > despite there being a message ready. > > If you can tolerate messages being delayed, there is an simple workaround > in which you call zmq_recv() periodically. We have code doing this by > specifying a timeout in the select() call. > > Dave > > > > ___ > zeromq-dev mailing list > zeromq-dev@lists.zeromq.org > http://lists.zeromq.org/mailman/listinfo/zeromq-dev > ___ zeromq-dev mailing list zeromq-dev@lists.zeromq.org http://lists.zeromq.org/mailman/listinfo/zeromq-dev
Re: [zeromq-dev] Fwd: 37/ZMTP RFC inconsistencies
Great, thanks. All the rest makes sense. On 24 May 2016 at 06:34, Pieter Hintjenswrote: > OK, done here: https://github.com/zeromq/rfc/pull/95 > > On Mon, May 23, 2016 at 11:11 PM, Elliot Crosby-McCullough < > elliot...@gmail.com> wrote: > >> >> >> On 23 May 2016 at 21:35, Pieter Hintjens wrote: >> >>> Yes, good catch. I need to double-check that, it may be that with NULL >>> we can strictly define the server as "binding peer" and client as >>> "connecting peer" since there's no security relationship. >>> >>> On Mon, May 23, 2016 at 7:34 PM, Elliot Crosby-McCullough >>> wrote: >>> > OK, cool. Does this line need updating then, as the NULL mechanism now >>> > describes client and server behaviours with regard to the sequencing of >>> > READY commands? >>> > >>> > https://github.com/zeromq/rfc/blob/master/spec_37.txt#L227 >>> > >>> > On 23 May 2016 at 18:20, Pieter Hintjens wrote: >>> >> >>> >> The as_server property lets you reverse the usual bind/connect >>> >> direction so that the client binds and the server connects. Without >>> >> this, it's per the usual default. >>> >> >>> >> On Mon, May 23, 2016 at 2:17 PM, Elliot Crosby-McCullough >>> >> wrote: >>> >> > Great, thanks. Since we're talking about a security mechanism that >>> >> > doesn't >>> >> > set `as_server` for either peer should I assume that the binding >>> peer is >>> >> > the >>> >> > "server" and the connecting peer is the "client", i.e. standard TCP >>> >> > terminology? >>> >> > >>> >> > On 23 May 2016 at 13:15, Pieter Hintjens wrote: >>> >> >> >>> >> >> I've made changes and sent a PR: >>> https://github.com/zeromq/rfc/pull/93 >>> >> >> >>> >> >> On Mon, May 23, 2016 at 2:11 PM, Pieter Hintjens >>> wrote: >>> >> >> > OK, there's an error in the explanation here. It's not >>> symmetric. The >>> >> >> > client is the one that needs to send its READY upfront. The >>> server is >>> >> >> > the one that checks the READY properties before sending its own >>> >> >> > READY. >>> >> >> > The example is correct; the text is not. Thanks for pointing this >>> >> >> > out. >>> >> >> > >>> >> >> > >>> >> >> > On Mon, May 23, 2016 at 1:54 PM, Elliot Crosby-McCullough >>> >> >> > wrote: >>> >> >> >> Hi Pieter, >>> >> >> >> >>> >> >> >> You're right, I noticed the more detailed description of the >>> partial >>> >> >> >> signature read shortly after posting, but I'm still not sure >>> about >>> >> >> >> the >>> >> >> >> worked example. As I mentioned there's also the conflict >>> between >>> >> >> >> waiting >>> >> >> >> for a READY, validating it, *then* sending your own READY as >>> per the >>> >> >> >> worked >>> >> >> >> example, while the spec says to send READY without waiting for >>> the >>> >> >> >> other >>> >> >> >> side to do so. >>> >> >> >> >>> >> >> >> All the best, >>> >> >> >> Elliot >>> >> >> >> >>> >> >> >> >>> >> >> >> On 22 May 2016 at 19:38, Pieter Hintjens wrote: >>> >> >> >>> >>> >> >> >>> The partial read is to deal with older versions of ZMTP. Peers >>> that >>> >> >> >>> do >>> >> >> >>> this won't deadlock since as soon as they've read the first 11 >>> >> >> >>> bytes >>> >> >> >>> they can send the rest of their own greeting, then they can >>> >> >> >>> validate >>> >> >> >>> the socket type, send READY, then wait for a READY. Peers that >>> >> >> >>> don't >>> >> >> >>> do backwards compatibility just send the whole greeting, wait >>> for >>> >> >> >>> the >>> >> >> >>> greeting, validate it, etc. >>> >> >> >>> >>> >> >> >>> >>> >> >> >>> On Sun, May 22, 2016 at 10:54 AM, Elliot Crosby-McCullough >>> >> >> >>> wrote: >>> >> >> >>> > Hi there! >>> >> >> >>> > >>> >> >> >>> > I'm working my way through an implementation of 37/ZMTP >>> >> >> >>> > (http://rfc.zeromq.org/spec:37) and there's a few >>> inconsistencies >>> >> >> >>> > in >>> >> >> >>> > the >>> >> >> >>> > spec, mostly the timing of message exchanges, and how it >>> differs >>> >> >> >>> > in >>> >> >> >>> > the >>> >> >> >>> > spec >>> >> >> >>> > proper from the worked example. >>> >> >> >>> > >>> >> >> >>> > Here's a couple of quotes where anti-deadlock approaches are >>> >> >> >>> > discussed: >>> >> >> >>> >> >>> >> >> >>> >> A peer that reads a full greeting, including mechanism, MUST >>> >> >> >>> >> also >>> >> >> >>> >> send >>> >> >> >>> >> a >>> >> >> >>> >> full greeting including mechanism. This avoids deadlocks in >>> >> >> >>> >> which >>> >> >> >>> >> two >>> >> >> >>> >> peers >>> >> >> >>> >> each wait for the other to divulge the remainder of their >>> >> >> >>> >> greeting. >>> >> >> >>> > >>> >> >> >>> > >>> >> >> >>> >> Note that to avoid deadlocks, each peer MUST send its READY >>> >> >> >>> >> command >>> >> >> >>> >> before >>> >> >> >>> >> attempting to receive a READY from the other peer. In the >>> NULL >>> >> >> >>> >> mechanism, >>>