diff options
| author | Matthias Radestock <matthias@rabbitmq.com> | 2013-01-22 15:09:33 +0000 |
|---|---|---|
| committer | Matthias Radestock <matthias@rabbitmq.com> | 2013-01-22 15:09:33 +0000 |
| commit | 6fdc8875d205347db625f978511c69c9eac4d980 (patch) | |
| tree | da2b996f4cf077131c0e187449ff7a883724d365 /packaging | |
| parent | b7751b9d8fa31ccc289a5708d9b0618581496b58 (diff) | |
| download | rabbitmq-server-git-6fdc8875d205347db625f978511c69c9eac4d980.tar.gz | |
prevent channel from sending anything after close/close_ok
The "we have sent a close/close_ok" state is indicated by
state=closing. Well, not quite...
The channel gets into the 'closing' state via notify_queues. That is
called in three places:
- 'terminate' - uninteresting since we don't send/do anything after
that anyway
- handle_exception when encountering a channel level error, i.e. when
we send a channel.close
- when receiving a 'channel.close'. Note that this isn't quite the
same as sending a channel.close_ok. That in fact happens later,
after a handshake with the reader. But for our purposes it's good
enough. Certainly logically it is perfectly ok for us to stop
sending things to the client once we have *seen* a 'close'.
So how do we prevent sending in the 'closing' state?
Firstly, we introduce a 'send' helper that replaces all
rabbit_writer:send_command/2 invocations and is a no-op when
state=closing. There is one notable exception - the sending of
'channel.close', which happens when state has already been set to
'closing'.
rabbit_writer:send_command/2 isn't the only way to send commands to
the writer though. The channel uses a few others:
- send_command_sync - this is used to send channel.close_ok. We are in
fact in the 'closing' state at that point and nevertheless must send
that command (this is the tail end of the aforementioned
handshake). So it's fine to leave this invocation as is.
- send_command_and_notify - this is used to send messages with
basic.deliver. We make that entire code a no-op in the no-op case,
i.e. any messages sent by queues to the channel while it is
'closing' are simply dropped on the floor. This is TRTTD since it
results in a minimum amount of work and is perfectly safe - no
different to the channel terminating while those messages were in
flight.
- send_command/3 - this is used to send a basic.get_ok. That entire
code - part of handle_method - is already guarded by a 'closing'
state check that no-ops. It is also used to send basic.returns,
which only happens in handling a basic.publish, which in turn is
subject to the same handle_method guard.
Finally, we add some optimisations to the 'confirm' and 'tx' code, so
that all the logic for aggregating confirms and sending acks/nacks (or
tx.commit / tx.commit failures) gets skipped when closing.
Diffstat (limited to 'packaging')
0 files changed, 0 insertions, 0 deletions
