FAQ

[rabbitmq-discuss] Linking to a channel process (erlang client)

Hunter Morris
Jun 14, 2011 at 5:22 pm
This is a rough continuation of
http://lists.rabbitmq.com/pipermail/rabbitmq-discuss/2010-September/009032.html
which is the only mailing list post I could find relevant to my issue.
(Aside: kudos to Matthew Sackman for clear explanations including
ASCII diagrams!)

I have a similar application to Erik which supervises a connection via
a worker and creates a channel per application worker process so that
channel exceptions kill only worker processes and the entire
supervision tree is torn down by a connection exception. In general
this works brilliantly well. However, on rare but possible occasions,
the following happens when a worker process opens a channel:

{ok, ChanPid} = amqp_connection:open_channel(ConnPid),
% self() dies due to exit signal from another linked process
link(ChanPid), % we never get here due to exit race

Unfortunately, this leaves a "hanging chad" channel in the supervision
tree. Am I missing something subtle? Is it possible to avoid such a
race?

Best,
Hunter Morris
reply

Search Discussions

3 responses

  • Matthew Sackman at Jun 14, 2011 at 11:45 pm

    On Tue, Jun 14, 2011 at 06:22:41PM +0100, Hunter Morris wrote:
    I have a similar application to Erik which supervises a connection via
    a worker and creates a channel per application worker process so that
    channel exceptions kill only worker processes and the entire
    supervision tree is torn down by a connection exception. In general
    this works brilliantly well. However, on rare but possible occasions,
    the following happens when a worker process opens a channel:

    {ok, ChanPid} = amqp_connection:open_channel(ConnPid),
    % self() dies due to exit signal from another linked process
    link(ChanPid), % we never get here due to exit race

    Unfortunately, this leaves a "hanging chad" channel in the supervision
    tree. Am I missing something subtle? Is it possible to avoid such a
    race?
    Hmm, that's tricky. Depends what you want to do really - you could have
    the supervisor link to the base process that is the amqp_client
    application if you want (before starting any workers), but it depends if
    you want death of your application to tear down the whole client -
    sequencing of those actions to achieve a safe, controlled shutdown, is
    not trivial.

    My understanding is that on the whole, libraries that spawn processes
    are linked to, or monitored, rather than linking / monitoring their
    clients. However, this may be wrong and/or not best practise. If you
    have ideas how this can be improved, please do let us know.

    Best wishes,

    Matthew
  • Hunter Morris at Jun 15, 2011 at 12:05 pm

    On Wed, Jun 15, 2011 at 12:45 AM, Matthew Sackman wrote:
    Hmm, that's tricky. Depends what you want to do really - you could have
    the supervisor link to the base process that is the amqp_client
    application if you want (before starting any workers), but it depends if
    you want death of your application to tear down the whole client -
    sequencing of those actions to achieve a safe, controlled shutdown, is
    not trivial.
    Currently, my application's top-level supervisor starts amqp_sup as a
    child itself which gives the behaviour I want when my application
    crashes. That works quite well and behaves as I expect.
    My understanding is that on the whole, libraries that spawn processes
    are linked to, or monitored, rather than linking / monitoring their
    clients. However, this may be wrong and/or not best practise. If you
    have ideas how this can be improved, please do let us know.
    My main concern is leaking processes since client-side channels are
    composed of at least 3 processes each (and I expect hundreds of
    channels in this particular application).

    I've seen other "client" applications which manage socket connections
    treat this issue very differently. For example, lhttpc
    (https://github.com/esl/lhttpc) spawn_links a simple lhttpc_client
    process, passing along self() in order to unlink when a request is
    finished. Obviously, HTTP clients are largely stateless which differs
    greatly from the situation we have with AMQP connections and channels.

    Based on a suggestion, I will most likely trap exits in the worker
    process while setting up the link to the channel in order to clean up
    if it receives an exit signal from elsewhere. Because the worker
    processes are quite simple, this should be fine.

    Thanks for your help,
    Hunter
  • Matthew Sackman at Jun 15, 2011 at 12:10 pm

    On Wed, Jun 15, 2011 at 01:05:44PM +0100, Hunter Morris wrote:
    I've seen other "client" applications which manage socket connections
    treat this issue very differently. For example, lhttpc
    (https://github.com/esl/lhttpc) spawn_links a simple lhttpc_client
    process, passing along self() in order to unlink when a request is
    finished. Obviously, HTTP clients are largely stateless which differs
    greatly from the situation we have with AMQP connections and channels.
    Interesting, and thanks for the pointer. I'll take a look at that and we
    may well change the behaviour here, or at least introduce a start_link
    variant as there used to be.

    Matthew

Related Discussions

Discussion Navigation
viewthread | post

2 users in discussion

Matthew Sackman: 2 posts Hunter Morris: 2 posts