zmq send with NOBLOCK raise Resource temporarily unavailable
Asked Answered
L

1

17

This code will raise Resource temporarily unavailable when call with NOBLOCK:

context = zmq.Context()
sender = context.socket(zmq.PUSH)
sender.bind('tcp://*:15556')
sender.send('KeEpAliv', zmq.NOBLOCK)  # this line will throw exception
#sender.send('KeEpAliv')  # this line will ok

After read the docs, I found no hints for this. but docs for recv explained this flag.

Legislator answered 17/2, 2014 at 10:22 Comment(0)
C
23

Python wrappers raise zmq.error.Again if the underlying C API returns EAGAIN.

Now, you should follow to zmq_send documentation, which states:

ZMQ_NOBLOCK
Specifies that the operation should be performed in non-blocking mode. If the message cannot be queued on the socket, the zmq_send() function shall fail with errno set to EAGAIN.

Also, in the errors section:

EAGAIN
Non-blocking mode was requested and the message cannot be sent at the moment.

Now, why is it not possible to send any message? On the page describing PUSH/PULL sockets we can read the following about the PUSH socket:

SHALL create this queue when a peer connects to it. If this peer disconnects, the PUSH socket SHALL destroy its queue and SHALL discard any messages it contains.

Before any peer connects to your socket, there's nowhere to send the messages, and there's no queue. Thus only 2 things are possible:

  • if you call send() in blocking mode, it blocks until a peer connects
  • if you call send() in non-blocking mode, it raises zmq.error.Again to inform you, that there's nothing that could be done with the message and you should try again later.

Note, that you can also get this exception if queues for each of the connected peers are full (PUSH socket creates a separate queue for each connected peer).

Conklin answered 25/2, 2014 at 21:57 Comment(3)
Thanks, this give me the hint: send() in non-blocking mode, it raises zmq.error.Again.Legislator
so, do I understand correctly that the only way to have such "dynamic queue" when pusher can send many messages before any pullers are connected is via a queue device? or "streamer" device? In fact I have tried the queue device for this (with PUSH-PULL sockets on both sides), it works ok. Just from reading the O'Reily book I expected it to be built into sockets. As I understand only PUSH-PULL sockets don't queue when there is nobody connected?Menfolk
that's my understanding, though I haven't touched ZMQ for ages now, things might have changed.Conklin

© 2022 - 2024 — McMap. All rights reserved.