Skip to content

Commit c5ce112

Browse files
committed
Merge branch 'michal/mnesia/fix-internal-message-leak/OTP-19855' into maint
* michal/mnesia/fix-internal-message-leak/OTP-19855: Use alias to prevent internal message leak after timeout
2 parents d196779 + 8a350bd commit c5ce112

File tree

4 files changed

+70
-22
lines changed

4 files changed

+70
-22
lines changed

lib/mnesia/src/mnesia.hrl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,17 @@
5555
(try ?ets_lookup_element(mnesia_gvar, Var, 2)
5656
catch error:_:_Stacktrace -> {'EXIT', _Stacktrace} end)).
5757

58+
-define(unalias_and_flush_msg(Alias, Msg),
59+
unalias(Alias),
60+
?flush_msg(Msg)
61+
).
62+
63+
-define(flush_msg(Msg),
64+
receive Msg -> ok
65+
after 0 -> ok
66+
end
67+
).
68+
5869
%% It's important that counter is first, since we compare tid's
5970

6071
-record(tid,

lib/mnesia/src/mnesia_controller.erl

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@
102102
dump_and_reply/2,
103103
load_and_reply/2,
104104
send_and_reply/2,
105-
wait_for_tables_init/2,
105+
wait_for_tables_init/3,
106106
connect_nodes2/3
107107
]).
108108

@@ -235,13 +235,16 @@ wait_for_tables(Tabs, Timeout) ->
235235
do_wait_for_tables(Tabs, 0) ->
236236
reply_wait(Tabs);
237237
do_wait_for_tables(Tabs, Timeout) ->
238-
Pid = spawn_link(?MODULE, wait_for_tables_init, [self(), Tabs]),
238+
Alias = alias([reply]),
239+
Pid = spawn_link(?MODULE, wait_for_tables_init, [self(), Alias, Tabs]),
239240
receive
240-
{?SERVER_NAME, Pid, Res} ->
241+
{?SERVER_NAME, Alias, Res} ->
241242
Res;
242243
{'EXIT', Pid, _} ->
244+
unalias(Alias),
243245
reply_wait(Tabs)
244246
after Timeout ->
247+
?unalias_and_flush_msg(Alias, {?SERVER_NAME, Alias, _}),
245248
unlink(Pid),
246249
exit(Pid, timeout),
247250
reply_wait(Tabs)
@@ -259,10 +262,10 @@ reply_wait(Tabs) ->
259262
catch exit:_ -> {error, {node_not_running, node()}}
260263
end.
261264

262-
wait_for_tables_init(From, Tabs) ->
265+
wait_for_tables_init(From, Alias, Tabs) ->
263266
process_flag(trap_exit, true),
264267
Res = wait_for_init(From, Tabs, whereis(?SERVER_NAME)),
265-
From ! {?SERVER_NAME, self(), Res},
268+
Alias ! {?SERVER_NAME, Alias, Res},
266269
unlink(From),
267270
exit(normal).
268271

@@ -1309,7 +1312,7 @@ handle_info(Msg = {'EXIT', Pid, R}, State) when R /= wait_for_tables_timeout ->
13091312
end;
13101313

13111314
handle_info({From, get_state}, State) ->
1312-
From ! {?SERVER_NAME, State},
1315+
From ! {?SERVER_NAME, From, State},
13131316
noreply(State);
13141317

13151318
%% No real need for buffering
@@ -1871,12 +1874,14 @@ get_info(Timeout) ->
18711874
undefined ->
18721875
{timeout, Timeout};
18731876
Pid ->
1874-
Pid ! {self(), get_state},
1877+
Alias = alias([reply]),
1878+
Pid ! {Alias, get_state},
18751879
receive
1876-
{?SERVER_NAME, State = #state{loader_queue=LQ,late_loader_queue=LLQ}} ->
1880+
{?SERVER_NAME, Alias, State = #state{loader_queue=LQ,late_loader_queue=LLQ}} ->
18771881
{info,State#state{loader_queue=gb_trees:to_list(LQ),
18781882
late_loader_queue=gb_trees:to_list(LLQ)}}
18791883
after Timeout ->
1884+
?unalias_and_flush_msg(Alias, {?SERVER_NAME, Alias, _}),
18801885
{timeout, Timeout}
18811886
end
18821887
end.
@@ -1886,11 +1891,13 @@ get_workers(Timeout) ->
18861891
undefined ->
18871892
{timeout, Timeout};
18881893
Pid ->
1889-
Pid ! {self(), get_state},
1894+
Alias = alias([reply]),
1895+
Pid ! {Alias, get_state},
18901896
receive
1891-
{?SERVER_NAME, State = #state{}} ->
1897+
{?SERVER_NAME, Alias, State = #state{}} ->
18921898
{workers, get_loaders(State), get_senders(State), State#state.dumper_pid}
18931899
after Timeout ->
1900+
?unalias_and_flush_msg(Alias, {?SERVER_NAME, Alias, _}),
18941901
{timeout, Timeout}
18951902
end
18961903
end.

lib/mnesia/src/mnesia_locker.erl

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1129,8 +1129,15 @@ rec_requests([], _Oid, _Store) ->
11291129
ok.
11301130

11311131
get_held_locks() ->
1132-
?MODULE ! {get_table, self(), mnesia_held_locks},
1133-
Locks = receive {mnesia_held_locks, Ls} -> Ls after 5000 -> [] end,
1132+
Alias = alias([reply]),
1133+
?MODULE ! {get_table, Alias, mnesia_held_locks},
1134+
Locks = receive
1135+
{mnesia_held_locks, Ls} ->
1136+
Ls
1137+
after 5000 ->
1138+
?unalias_and_flush_msg(Alias, {mnesia_held_locks, _}),
1139+
[]
1140+
end,
11341141
rewrite_locks(Locks, []).
11351142

11361143
%% Mnesia internal usage only
@@ -1151,8 +1158,15 @@ rewrite_locks([], Acc) ->
11511158
lists:reverse(Acc).
11521159

11531160
get_lock_queue() ->
1154-
?MODULE ! {get_table, self(), mnesia_lock_queue},
1155-
Q = receive {mnesia_lock_queue, Locks} -> Locks after 5000 -> [] end,
1161+
Alias = alias([reply]),
1162+
?MODULE ! {get_table, Alias, mnesia_lock_queue},
1163+
Q = receive
1164+
{mnesia_lock_queue, Locks} ->
1165+
Locks
1166+
after 5000 ->
1167+
?unalias_and_flush_msg(Alias, {mnesia_lock_queue, _}),
1168+
[]
1169+
end,
11561170
[{Oid, Op, Pid, Tid, WFT} || {queue, Oid, Tid, Op, Pid, WFT} <- Q].
11571171

11581172
do_stop() ->

lib/mnesia/src/mnesia_tm.erl

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1111,8 +1111,12 @@ intercept_best_friend([{stop,Fun} | R],Ignore) ->
11111111
?CATCH(Fun()),
11121112
intercept_best_friend(R,Ignore);
11131113
intercept_best_friend([Pid | R],false) ->
1114-
Pid ! {activity_ended, undefined, self()},
1114+
Alias = alias([reply]),
1115+
Pid ! {activity_ended, undefined, Alias},
11151116
wait_for_best_friend(Pid, 0),
1117+
unalias(Alias),
1118+
?flush_msg({activity_ended, _, Pid}),
1119+
?flush_msg({'EXIT', Pid, _}),
11161120
intercept_best_friend(R,true);
11171121
intercept_best_friend([_|R],true) ->
11181122
intercept_best_friend(R,true).
@@ -2052,8 +2056,9 @@ sync_send_dirty(Tid, [Head | Tail], Tab, WaitFor) ->
20522056
Res = do_dirty(Tid, Head),
20532057
{WF, Res};
20542058
true ->
2055-
{?MODULE, Node} ! {self(), {sync_dirty, Tid, Head, Tab}},
2056-
sync_send_dirty(Tid, Tail, Tab, [Node | WaitFor])
2059+
Alias = alias([reply]),
2060+
{?MODULE, Node} ! {Alias, {sync_dirty, Tid, Head, Tab}},
2061+
sync_send_dirty(Tid, Tail, Tab, [{Node, Alias} | WaitFor])
20572062
end;
20582063
sync_send_dirty(_Tid, [], _Tab, WaitFor) ->
20592064
{WaitFor, {'EXIT', {aborted, {node_not_running, WaitFor}}}}.
@@ -2071,18 +2076,27 @@ async_send_dirty(Tid, [Head | Tail], Tab, ReadNode, WaitFor, Res) ->
20712076
NewRes = do_dirty(Tid, Head),
20722077
async_send_dirty(Tid, Tail, Tab, ReadNode, WaitFor, NewRes);
20732078
ReadNode == Node ->
2074-
{?MODULE, Node} ! {self(), {sync_dirty, Tid, Head, Tab}},
2079+
Alias = alias([reply]),
2080+
{?MODULE, Node} ! {Alias, {sync_dirty, Tid, Head, Tab}},
20752081
NewRes = {'EXIT', {aborted, {node_not_running, Node}}},
2076-
async_send_dirty(Tid, Tail, Tab, ReadNode, [Node | WaitFor], NewRes);
2082+
async_send_dirty(Tid, Tail, Tab, ReadNode, [{Node, Alias} | WaitFor], NewRes);
20772083
true ->
20782084
{?MODULE, Node} ! {self(), {async_dirty, Tid, Head, Tab}},
20792085
async_send_dirty(Tid, Tail, Tab, ReadNode, WaitFor, Res)
20802086
end;
20812087
async_send_dirty(_Tid, [], _Tab, _ReadNode, WaitFor, Res) ->
20822088
{WaitFor, Res}.
20832089

2084-
rec_dirty([Node | Tail], Res) when Node /= node() ->
2085-
NewRes = get_dirty_reply(Node, Res),
2090+
rec_dirty([{Node, Alias} | Tail], Res) when Node /= node() ->
2091+
NewRes =
2092+
try
2093+
get_dirty_reply(Node, Res)
2094+
after
2095+
unalias(Alias),
2096+
?flush_msg({?MODULE, Node, {'EXIT', _}}),
2097+
?flush_msg({?MODULE, Node, {dirty_res, _}}),
2098+
?flush_msg({mnesia_down, Node})
2099+
end,
20862100
rec_dirty(Tail, NewRes);
20872101
rec_dirty([], Res) ->
20882102
Res.
@@ -2206,11 +2220,13 @@ get_info(Timeout) ->
22062220
undefined ->
22072221
{timeout, Timeout};
22082222
Pid ->
2209-
Pid ! {self(), info},
2223+
Alias = alias([reply]),
2224+
Pid ! {Alias, info},
22102225
receive
22112226
{?MODULE, _, {info, Part, Coord}} ->
22122227
{info, Part, Coord}
22132228
after Timeout ->
2229+
?unalias_and_flush_msg(Alias, {?MODULE, _, {info, _, _}}),
22142230
{timeout, Timeout}
22152231
end
22162232
end.

0 commit comments

Comments
 (0)