summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/mnesia/src/mnesia_loader.erl18
-rw-r--r--lib/mnesia/test/mnesia_evil_coverage_test.erl53
2 files changed, 60 insertions, 11 deletions
diff --git a/lib/mnesia/src/mnesia_loader.erl b/lib/mnesia/src/mnesia_loader.erl
index 274941d1af..4dea366964 100644
--- a/lib/mnesia/src/mnesia_loader.erl
+++ b/lib/mnesia/src/mnesia_loader.erl
@@ -1014,15 +1014,15 @@ finish_copy(Pid, Tab, Storage, RemoteS, NeedLock) ->
mnesia_checkpoint:tm_add_copy(Tab, RecNode),
DatBin = dat2bin(Tab, ?catch_val({Tab, storage_type}), RemoteS),
Pid ! {self(), {no_more, DatBin}},
- cleanup_tab_copier(Pid, Storage, Tab)
- end,
- receive
- {Pid, no_more} -> % Dont bother about the spurious 'more' message
- no_more;
- {copier_done, Node} ->
- verbose("Tab receiver ~tp crashed (more): ~p~n", [Tab, Node]),
- receiver_died
- end
+ cleanup_tab_copier(Pid, Storage, Tab),
+ receive
+ {Pid, no_more} -> % Dont bother about the spurious 'more' message
+ no_more;
+ {copier_done, Node} ->
+ verbose("Tab receiver ~tp crashed (more): ~p~n", [Tab, Node]),
+ receiver_died
+ end
+ end
end,
mnesia:transaction(Trans).
diff --git a/lib/mnesia/test/mnesia_evil_coverage_test.erl b/lib/mnesia/test/mnesia_evil_coverage_test.erl
index 68ab9a53b7..b467d92f9b 100644
--- a/lib/mnesia/test/mnesia_evil_coverage_test.erl
+++ b/lib/mnesia/test/mnesia_evil_coverage_test.erl
@@ -30,7 +30,7 @@
-export([system_info/1, table_info/1, error_description/1,
db_node_lifecycle/1, evil_delete_db_node/1, start_and_stop/1,
checkpoint/1, table_lifecycle/1, storage_options/1,
- add_copy_conflict/1, add_copy_when_going_down/1,
+ add_copy_conflict/1, add_copy_when_going_down/1, add_copy_when_dst_going_down/1,
add_copy_with_down/1,
replica_management/1, clear_table_during_load/1,
schema_availability/1, local_content/1,
@@ -66,7 +66,8 @@ all() ->
db_node_lifecycle, evil_delete_db_node, start_and_stop,
checkpoint, table_lifecycle, storage_options,
add_copy_conflict,
- add_copy_when_going_down, add_copy_with_down, replica_management,
+ add_copy_when_going_down, add_copy_when_dst_going_down, add_copy_with_down,
+ replica_management,
clear_table_during_load,
schema_availability, local_content,
{group, table_access_modifications}, replica_location,
@@ -735,6 +736,54 @@ add_copy_when_going_down(Config) ->
?match_receive({test,{aborted,_}}),
?verify_mnesia([Node2], []).
+add_copy_when_dst_going_down(suite) -> [];
+add_copy_when_dst_going_down(doc) ->
+ ["Table copy destination node goes down. Verify that the issue fixed in erlang/otp#6013 doesn't happen again, whitebox testing."];
+add_copy_when_dst_going_down(Config) ->
+ [Node1, Node2] = ?acquire_nodes(2, Config),
+ ?match({atomic, ok}, mnesia:create_table(a, [{ram_copies, [Node1]}])),
+ lists:foreach(fun(I) ->
+ ok = mnesia:sync_dirty(fun() -> mnesia:write({a, I, I}) end)
+ end,
+ lists:seq(1, 100000)),
+ ?match({ok, _}, mnesia:change_config(extra_db_nodes, [Node2])),
+
+ %% Start table copy
+ Tester = self(),
+ spawn_link(fun() ->
+ mnesia:add_table_copy(a, Node2, ram_copies),
+ Tester ! add_table_copy_finished
+ end),
+ timer:sleep(10), % Wait for `mnesia_loader:send_more/6` has started
+
+ %% Grab a write lock
+ spawn_link(fun() ->
+ Fun = fun() ->
+ ok = mnesia:write_lock_table(a),
+ Tester ! {write_lock_acquired, self()},
+ receive node2_mnesia_killed -> ok
+ end,
+ Tester ! write_lock_released,
+ ok
+ end,
+ mnesia:transaction(Fun)
+ end),
+ receive {write_lock_acquired, Locker} -> ok
+ end,
+ timer:sleep(200), % Wait for `mnesia_loader:send_more/6` has finished
+ ?match([], mnesia_test_lib:kill_mnesia([Node2])),
+ Locker ! node2_mnesia_killed,
+
+ receive write_lock_released -> ok
+ end,
+ receive add_table_copy_finished -> ok
+ end,
+ timer:sleep(1000), % Wait for `mnesia_loader:finish_copy/5` has acquired the read lock
+
+ %% Grab a write lock
+ ?match({atomic, ok}, mnesia:transaction(fun() -> mnesia:write_lock_table(a) end, 10)),
+ ?verify_mnesia([Node1], []).
+
add_copy_with_down(suite) -> [];
add_copy_with_down(Config) ->
%% Allow add_table_copy() with ram_copies even all other replicas are down