summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMichael Klishin <michael@clojurewerkz.org>2016-01-09 20:30:04 +0300
committerMichael Klishin <michael@clojurewerkz.org>2016-01-09 20:30:04 +0300
commit438f16d2b8af9099c36bb2cac36621dcb932786d (patch)
tree762f8a14db2316786cd8fd95c558d8d472ea7493 /src
parent26b670a90e2b27e8d09fcba34a8f2e59d9a47147 (diff)
downloadrabbitmq-server-git-438f16d2b8af9099c36bb2cac36621dcb932786d.tar.gz
Ensure exchange-delete-in-progress is always cleared
Diffstat (limited to 'src')
-rw-r--r--src/rabbit_exchange.erl47
1 files changed, 29 insertions, 18 deletions
diff --git a/src/rabbit_exchange.erl b/src/rabbit_exchange.erl
index fe1fa1a19e..28222c54fd 100644
--- a/src/rabbit_exchange.erl
+++ b/src/rabbit_exchange.erl
@@ -166,6 +166,10 @@ declare(XName, Type, Durable, AutoDelete, Internal, Args) ->
XT = type_to_module(Type),
%% We want to upset things if it isn't ok
ok = XT:validate(X),
+ %% Avoid a channel exception if there's a race condition
+ %% with an exchange.delete operation.
+ %%
+ %% See rabbitmq/rabbitmq-federation#7.
case rabbit_runtime_parameters:lookup(XName#resource.virtual_host,
<<"exchange-delete-in-progress">>,
XName#resource.name) of
@@ -435,24 +439,31 @@ delete(XName, IfUnused) ->
true -> fun conditional_delete/2;
false -> fun unconditional_delete/2
end,
- rabbit_runtime_parameters:set(XName#resource.virtual_host,
- <<"exchange-delete-in-progress">>,
- XName#resource.name, true, none),
- call_with_exchange(
- XName,
- fun (X) ->
- case Fun(X, false) of
- {deleted, X, Bs, Deletions} ->
- rabbit_binding:process_deletions(
- rabbit_binding:add_deletion(
- XName, {X, deleted, Bs}, Deletions));
- {error, _InUseOrNotFound} = E ->
- rabbit_misc:const(E)
- end
- end),
- rabbit_runtime_parameters:clear(XName#resource.virtual_host,
- <<"exchange-delete-in-progress">>,
- XName#resource.name).
+ try
+ %% guard exchange.declare operations from failing when there's
+ %% a race condition between it and an exchange.delete.
+ %%
+ %% see rabbitmq/rabbitmq-federation#7
+ rabbit_runtime_parameters:set(XName#resource.virtual_host,
+ <<"exchange-delete-in-progress">>,
+ XName#resource.name, true, none),
+ call_with_exchange(
+ XName,
+ fun (X) ->
+ case Fun(X, false) of
+ {deleted, X, Bs, Deletions} ->
+ rabbit_binding:process_deletions(
+ rabbit_binding:add_deletion(
+ XName, {X, deleted, Bs}, Deletions));
+ {error, _InUseOrNotFound} = E ->
+ rabbit_misc:const(E)
+ end
+ end)
+ after
+ rabbit_runtime_parameters:clear(XName#resource.virtual_host,
+ <<"exchange-delete-in-progress">>,
+ XName#resource.name)
+ end.
validate_binding(X = #exchange{type = XType}, Binding) ->
Module = type_to_module(XType),