I agree with the method used in the gist linked in your email:
First check amqp_frames_enqueued(). If this returns true, there are decoded
frames ready, amqp_simple_wait_frame() will not block.
Second check amqp_data_in_buffer(). If this returns true, there is data
that has already been received (with recv()) but not decoded. It is likely
if you call amqp_simple_wait_frame() it will not block. However if the data
in the buffer doesn't complete a frame, recv() will be called and may block.
Third, call select() or poll() on the socket associated with the connection
(you can use amqp_get_sockfd() to get the socket descriptor). If this
system call shows that the socket can be read from amqp_simple_wait_frame()
will call recv() and likely won't block - assuming a full frame is received.
As you may notice the last two steps don't give you a "correct all the
time" answer to whether amqp_simple_wait_frame() will block or not. In
practice I've found the majority of the time the above works well enough
for RPC-style AMQP messaging for the following two reasons:
1. When the broker sends data - typically it sends it as an entire frame,
if your select() call returns that there is data in the buffer likely you
already have, or soon will have an entire frame ready to be read by recv()
2. AMQP is intended to be run on a low-latency, high-bandwidth LAN, so if
you do get a partial frame when recv is called, within a short time period
you will receive the rest of the frame, otherwise it is likely something
serious has happened and that will cause the whole connection to die at
some point in the near future (possibly time out - which I grant you can
possibly block for a lengthy amount of time).
There is definitely room for improvement in the rabbitmq-c library handles
On Feb 15, 2012, at 2:28 PM, Brett Cameron wrote:
I'd look at implementing something along the lines of what Alex describes
in the link using select() or poll(). Have cc'd Alan for his consideration
as to how this might best be done. The approach outlined by Alex in the
link is okay, but you could still potentially find yourself hanging on a
blocked read if something bad happened between the initial check for data
available and a read operation. An alternative might be to add a timeout
parameter to the wait_frame call or create a variant of this function that
includes a timeout...