diff options
| author | Jean-Sébastien Pédron <jean-sebastien@rabbitmq.com> | 2020-04-08 14:56:16 +0200 |
|---|---|---|
| committer | Jean-Sébastien Pédron <jean-sebastien@rabbitmq.com> | 2020-04-09 10:21:19 +0200 |
| commit | 9f4b27736ab7569f952828963ef3371aa95d3ac9 (patch) | |
| tree | a7edc99866ef8d42f5fbae3266da0aa0d9cbbba4 /src | |
| parent | 91d17eb28a81b682b3ce4a4a388d5269e04ddf75 (diff) | |
| download | rabbitmq-server-git-9f4b27736ab7569f952828963ef3371aa95d3ac9.tar.gz | |
rabbit_feature_flags: Fix concurrent registry module reload
By calling code:delete() ourselves, we created a time window where there
is no registry module loaded between that call and the following
code:load_binary().
This meant that a concurrent access to the registry would trigger a load
of the initial uninitialized registry module from disk. That module
would then trigger a reload itself, leading to possible deadlock.
In fact, in code:load_binary(), the code server already takes care of
replacing the module atomically. We don't need to do anything.
Diffstat (limited to 'src')
| -rw-r--r-- | src/rabbit_feature_flags.erl | 14 |
1 files changed, 13 insertions, 1 deletions
diff --git a/src/rabbit_feature_flags.erl b/src/rabbit_feature_flags.erl index fd365fde55..0cddd1b66e 100644 --- a/src/rabbit_feature_flags.erl +++ b/src/rabbit_feature_flags.erl @@ -1287,8 +1287,20 @@ load_registry_mod(Mod, Bin) -> rabbit_log_feature_flags:debug( "Feature flags: acquired lock before reloading registry module (~p)", [self()]), + %% We want to make sure that the old registry (not the one being + %% currently in use) is purged by the code server. It means no + %% process lingers on that old code. + %% + %% We use code:soft_purge() for that (meaning no process is killed) + %% and we wait in an infinite loop for that to succeed. ok = purge_old_registry(Mod), - true = code:delete(Mod), + %% Now we can replace the currently loaded registry by the new one. + %% The code server takes care of marking the current registry as old + %% and load the new module in an atomic operation. + %% + %% Therefore there is no chance of a window where there is no + %% registry module available, causing the one on disk to be + %% reloaded. Ret = code:load_binary(Mod, FakeFilename, Bin), rabbit_log_feature_flags:debug( "Feature flags: releasing lock after reloading registry module (~p)", |
