Make queue.bind after basic.consume (rabbitmq-c)

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

Make queue.bind after basic.consume (rabbitmq-c)

Haster
Hi there

Is it safety to call queue.bind after basic.consume?

I use this test case and sometimes my program hangs on:
0: c000000000546f10 : __syscall_0504() + 0x30 (/lib/hpux64/libc.so.1)
1: c0000000000257a0 : __recv() at /ux/core/lan/src/NET/libxnet/x_recv.c:34
2: c0000000043e2080 : wchar_t() at amqp_socket.c:220
3: c0000000043e24b0 : signed char() at amqp_socket.c:316
4: c0000000043e2960 : signed char() at amqp_socket.c:385
5: c0000000043d6be0 : signed char() at amqp_framing.c:1953
6: c00000000a9b34d0 : RabbitMQ::RabbitMQQueueImpl::bind(RabbitMQ::RabbitMQExchange*,std::basic_string<char,std::char_traits<char>,std::allocator<char> > const&)() at RabbitMQQueueImpl.cpp:167

So maybe this test case is wrong and I should call basic.cancel befor I can call queue.bind again?
Reply | Threaded
Open this post in threaded view
|

Re: Make queue.bind after basic.consume (rabbitmq-c)

michaelklishin

2013/7/8 Haster <[hidden email]>
So maybe this test case is wrong and I should call basic.cancel befor I can
call queue.bind again?

There are no limitations on when you can call queue.bind as long as the queue
and the exchange your are binding exist.

There is one tricky scenario: if you basic.cancel the last consumer on an auto-delete
queue, it will be deleted.

What may be happening is rabbitmq-c expecting deliveries and getting
queue.bind-ok instead. Clients should handle such situation.
--
MK

http://github.com/michaelklishin
http://twitter.com/michaelklishin

_______________________________________________
rabbitmq-discuss mailing list
[hidden email]
https://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Make queue.bind after basic.consume (rabbitmq-c)

Haster
Michael, thanks for reply!

But as I understand hangs up take place in sync method recv (that waits packet infinitely - timeout = 0)
Reply | Threaded
Open this post in threaded view
|

Re: Make queue.bind after basic.consume (rabbitmq-c)

alan.antonuk
In reply to this post by michaelklishin
On Mon, Jul 8, 2013 at 2:43 AM, Michael Klishin <[hidden email]> wrote:

There is one tricky scenario: if you basic.cancel the last consumer on an auto-delete
queue, it will be deleted.

If the queue happens to be deleted before you try and queue.bind it, the broker will return a channel exception. In terms of the rabbitmq-c API the amqp_queue_bind() function should return null, then amqp_get_rpc_reply() will return the reason for the channel exception.  It shouldn't block for long on a recv() when doing one of these.

If you're reading messages using amqp_simple_wait_frame() it is possible to ignore a frame that shouldn't be ignored (like an channel.close or a connection.close). Could you describe in more detail what you're doing before it hangs?

_______________________________________________
rabbitmq-discuss mailing list
[hidden email]
https://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Make queue.bind after basic.consume (rabbitmq-c)

Haster
Alan, thanks for reply.

I was wrong when said that there is only one thread... I have to of them:

first thread creates all things (connection, channels to queue and exchanges), call basic.consume and start new thread that reads messages from queue and processes them...

But first thread can call one method, that add some binds and maybe declare new exchanges

At that moment I don't sync this threads

But can it be the root of problem?
I use separate channel for each used exchange and queue.
Reply | Threaded
Open this post in threaded view
|

Re: Make queue.bind after basic.consume (rabbitmq-c)

amvyas82
This post has NOT been accepted by the mailing list yet.
This is little old post but I am hitting this too.

I am using rabbitmq-c and Here is the flow:

This is a message processing thread:
amqp_exchange_declare
amqp_queue_declare
while (1) {
  if (consume_done) {
    amqp_maybe_release_buffers
    amqp_consume_message
    app specific processing.
  }
}

This is main app thread:
On getting to know a binding key, which happens later:
amqp_queue_bind
if (!consume_done) {
  amqp_basic_consume
  consume_done
}
There are multiple binding keys learnt at a later stage and so the above routine gets called multiple times in main app thread context.

The first time biding is successful and I also get messages. But second time amqp_queue_bind call hangs. On coring with SIGSEGV, I see following trace:
poll
recv_with_timeout
wait_frame_inner
amqp_simple_rpc
amqp_simple_rpc_decoded
amqp_queue_bind
Reply | Threaded
Open this post in threaded view
|

Re: Make queue.bind after basic.consume (rabbitmq-c)

amvyas82
This post has NOT been accepted by the mailing list yet.
I also see following comment in rabbitmq-c code (I am using rabbitmq-c-0.7.1)

wait_frame_inner
    ...
    /* TODO this needs to wait for a _frame_ and not anything written from the
     * socket */
    res = recv_with_timeout(state, deadline);

Not sure if the is hurting me.

-Ashish
Reply | Threaded
Open this post in threaded view
|

Re: Make queue.bind after basic.consume (rabbitmq-c)

amvyas82
This post has NOT been accepted by the mailing list yet.
Here is the app flow:

There is a message processing thread:

amqp_exchange_declare
amqp_queue_declare
while (1) {
  if (consume_done) {
    amqp_maybe_release_buffers
    amqp_consume_message
    app specific processing.
  }
}
This is main app thread: On getting to know a binding key, which happens later:

amqp_queue_bind
if (!consume_done) {
  amqp_basic_consume
  consume_done
}
There are multiple binding keys learnt at a later stage and so the above routine gets called multiple times in main app thread context.

The first time biding is successful and I also get messages. But second time amqp_queue_bind call hangs.

Here, the problem is message processing thread is doing amqp_consume_message with infinite timeout and we should not expect amqp_queue_bind to go through from main thread in this condition.

The solution is to call amqp_queue_bind only when amqp_consume_message is not waiting for messages.

It now seems it is so silly of me to have made this mistake.