aboutsummaryrefslogtreecommitdiffstats
path: root/lib/mnesia
diff options
context:
space:
mode:
Diffstat (limited to 'lib/mnesia')
-rw-r--r--lib/mnesia/src/mnesia.erl8
-rw-r--r--lib/mnesia/src/mnesia_controller.erl7
-rw-r--r--lib/mnesia/src/mnesia_loader.erl17
-rw-r--r--lib/mnesia/src/mnesia_tm.erl2
-rw-r--r--lib/mnesia/test/mnesia_test_lib.erl1
-rw-r--r--lib/mnesia/test/mnesia_trans_access_test.erl10
6 files changed, 34 insertions, 11 deletions
diff --git a/lib/mnesia/src/mnesia.erl b/lib/mnesia/src/mnesia.erl
index 9586adbf93..5bf2fc2dc3 100644
--- a/lib/mnesia/src/mnesia.erl
+++ b/lib/mnesia/src/mnesia.erl
@@ -1409,8 +1409,14 @@ select_cont(Tid,_,State=#mnesia_select{tid=Tid,written=[]}) ->
select_state(dirty_sel_cont(State),State);
select_cont(Tid,_Ts,State=#mnesia_select{tid=Tid}) ->
trans_select(dirty_sel_cont(State), State);
-select_cont(_Tid2,_,#mnesia_select{tid=_Tid1}) -> % Missmatching tids
+select_cont(Tid2,_,#mnesia_select{tid=_Tid1})
+ when element(1,Tid2) == tid -> % Mismatching tids
abort(wrong_transaction);
+select_cont(Tid,Ts,State=#mnesia_select{}) ->
+ % Repair mismatching tids in non-transactional contexts
+ RepairedState = State#mnesia_select{tid = Tid, written = [],
+ spec = undefined, type = undefined},
+ select_cont(Tid,Ts,RepairedState);
select_cont(_,_,Cont) ->
abort({badarg, Cont}).
diff --git a/lib/mnesia/src/mnesia_controller.erl b/lib/mnesia/src/mnesia_controller.erl
index 4791e2e290..17b47c059e 100644
--- a/lib/mnesia/src/mnesia_controller.erl
+++ b/lib/mnesia/src/mnesia_controller.erl
@@ -1703,9 +1703,10 @@ add_active_replica(Tab, Node, Cs = #cstruct{}) ->
block_table(Tab) ->
Var = {Tab, where_to_commit},
- Old = val(Var),
- New = {blocked, Old},
- set(Var, New). % where_to_commit
+ case is_tab_blocked(val(Var)) of
+ {true, _} -> ok;
+ {false, W2C} -> set(Var, mark_blocked_tab(true, W2C))
+ end.
unblock_table(Tab) ->
call({unblock_table, Tab}).
diff --git a/lib/mnesia/src/mnesia_loader.erl b/lib/mnesia/src/mnesia_loader.erl
index 71e5829c87..c710470a2c 100644
--- a/lib/mnesia/src/mnesia_loader.erl
+++ b/lib/mnesia/src/mnesia_loader.erl
@@ -342,9 +342,12 @@ spawned_receiver(ReplyTo,Tab,Storage,Cs, SenderPid,TabSize,DetsData, Init) ->
Done = do_init_table(Tab,Storage,Cs,
SenderPid,TabSize,DetsData,
ReplyTo, Init),
- ReplyTo ! {self(),Done},
- unlink(ReplyTo),
- unlink(whereis(mnesia_controller)),
+ try
+ ReplyTo ! {self(),Done},
+ unlink(ReplyTo),
+ unlink(whereis(mnesia_controller))
+ catch _:_ -> ok %% avoid error reports when stopping down mnesia
+ end,
exit(normal).
wait_on_load_complete(Pid) ->
@@ -916,9 +919,15 @@ send_packet(_N, _Pid, _Chunk, DataState) ->
finish_copy(Pid, Tab, Storage, RemoteS, NeedLock) ->
RecNode = node(Pid),
DatBin = dat2bin(Tab, Storage, RemoteS),
+ Node = node(Pid),
Trans =
fun() ->
NeedLock andalso mnesia:read_lock_table(Tab),
+ %% Check that receiver is still alive
+ receive {copier_done, Node} ->
+ throw(receiver_died)
+ after 0 -> ok
+ end,
A = val({Tab, access_mode}),
mnesia_controller:sync_and_block_table_whereabouts(Tab, RecNode, RemoteS, A),
cleanup_tab_copier(Pid, Storage, Tab),
@@ -927,7 +936,7 @@ finish_copy(Pid, Tab, Storage, RemoteS, NeedLock) ->
receive
{Pid, no_more} -> % Dont bother about the spurious 'more' message
no_more;
- {copier_done, Node} when Node == node(Pid)->
+ {copier_done, Node} ->
verbose("Tab receiver ~p crashed (more): ~p~n", [Tab, Node]),
receiver_died
end
diff --git a/lib/mnesia/src/mnesia_tm.erl b/lib/mnesia/src/mnesia_tm.erl
index b116b48312..388b42cf15 100644
--- a/lib/mnesia/src/mnesia_tm.erl
+++ b/lib/mnesia/src/mnesia_tm.erl
@@ -950,7 +950,7 @@ return_abort(Fun, Args, Reason) ->
if
Level == 1 ->
mnesia_locker:async_release_tid(Nodes, Tid),
- ?MODULE ! {delete_transaction, Tid},
+ ?SAFE(?MODULE ! {delete_transaction, Tid}),
erase(mnesia_activity_state),
flush_downs(),
?SAFE(unlink(whereis(?MODULE))),
diff --git a/lib/mnesia/test/mnesia_test_lib.erl b/lib/mnesia/test/mnesia_test_lib.erl
index 6e84a27ec9..0fabdc7929 100644
--- a/lib/mnesia/test/mnesia_test_lib.erl
+++ b/lib/mnesia/test/mnesia_test_lib.erl
@@ -263,6 +263,7 @@ slave_start_link(Host, Name, Retries) ->
Path = code:get_path(),
ok = rpc:call(NewNode, file, set_cwd, [Cwd]),
true = rpc:call(NewNode, code, set_path, [Path]),
+ ok = rpc:call(NewNode, error_logger, tty, [false]),
spawn_link(NewNode, ?MODULE, slave_sup, []),
rpc:multicall([node() | nodes()], global, sync, []),
{ok, NewNode};
diff --git a/lib/mnesia/test/mnesia_trans_access_test.erl b/lib/mnesia/test/mnesia_trans_access_test.erl
index aa50ee4cb1..4ed73ea859 100644
--- a/lib/mnesia/test/mnesia_trans_access_test.erl
+++ b/lib/mnesia/test/mnesia_trans_access_test.erl
@@ -307,6 +307,7 @@ select14(Config) when is_list(Config) ->
%% Some Helpers
Trans = fun(Fun) -> mnesia:transaction(Fun) end,
+ Dirty = fun(Fun) -> mnesia:async_dirty(Fun) end,
LoopHelp = fun('$end_of_table',_) -> [];
({Recs,Cont},Fun) ->
Sel = mnesia:select(Cont),
@@ -334,8 +335,13 @@ select14(Config) when is_list(Config) ->
?match({atomic, [OneRec]}, Trans(fun() -> Loop(Tab, OnePat) end)),
?match({atomic, All}, Trans(fun() -> Loop(Tab, AllPat) end)),
- {atomic,{_, Cont}} = Trans(fun() -> mnesia:select(Tab, OnePat, 1, read) end),
- ?match({aborted, wrong_transaction}, Trans(fun() -> mnesia:select(Cont) end)),
+ {atomic,{_, ContOne}} = Trans(fun() -> mnesia:select(Tab, OnePat, 1, read) end),
+ ?match({aborted, wrong_transaction}, Trans(fun() -> mnesia:select(ContOne) end)),
+ ?match('$end_of_table', Dirty(fun() -> mnesia:select(ContOne) end)),
+
+ {atomic,{_, ContAll}} = Trans(fun() -> mnesia:select(Tab, AllPat, 1, read) end),
+ ?match({aborted, wrong_transaction}, Trans(fun() -> mnesia:select(ContAll) end)),
+ ?match({[_], _}, Dirty(fun() -> mnesia:select(ContAll) end)),
?match({aborted, _}, Trans(fun() -> mnesia:select(Tab, {match, '$1', 2},1,read) end)),
?match({aborted, _}, Trans(fun() -> mnesia:select(Tab, [{'_', [], '$1'}],1,read) end)),