Skip to content

Commit db1d3bb

Browse files
committed
Use alias to prevent internal message leak after timeout
1 parent 412bff5 commit db1d3bb

File tree

4 files changed

+69
-22
lines changed

4 files changed

+69
-22
lines changed

lib/mnesia/src/mnesia.hrl

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

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

5869
-record(tid,

lib/mnesia/src/mnesia_controller.erl

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@
9999
dump_and_reply/2,
100100
load_and_reply/2,
101101
send_and_reply/2,
102-
wait_for_tables_init/2,
102+
wait_for_tables_init/3,
103103
connect_nodes2/3
104104
]).
105105

@@ -232,13 +232,15 @@ wait_for_tables(Tabs, Timeout) ->
232232
do_wait_for_tables(Tabs, 0) ->
233233
reply_wait(Tabs);
234234
do_wait_for_tables(Tabs, Timeout) ->
235-
Pid = spawn_link(?MODULE, wait_for_tables_init, [self(), Tabs]),
235+
Alias = alias([reply]),
236+
Pid = spawn_link(?MODULE, wait_for_tables_init, [self(), Alias, Tabs]),
236237
receive
237-
{?SERVER_NAME, Pid, Res} ->
238+
{?SERVER_NAME, Alias, Res} ->
238239
Res;
239240
{'EXIT', Pid, _} ->
240241
reply_wait(Tabs)
241242
after Timeout ->
243+
?unalias_and_flush_msg(Alias, {?SERVER_NAME, Alias, _}),
242244
unlink(Pid),
243245
exit(Pid, timeout),
244246
reply_wait(Tabs)
@@ -256,10 +258,10 @@ reply_wait(Tabs) ->
256258
catch exit:_ -> {error, {node_not_running, node()}}
257259
end.
258260

259-
wait_for_tables_init(From, Tabs) ->
261+
wait_for_tables_init(From, Alias, Tabs) ->
260262
process_flag(trap_exit, true),
261263
Res = wait_for_init(From, Tabs, whereis(?SERVER_NAME)),
262-
From ! {?SERVER_NAME, self(), Res},
264+
Alias ! {?SERVER_NAME, Alias, Res},
263265
unlink(From),
264266
exit(normal).
265267

@@ -1306,7 +1308,7 @@ handle_info(Msg = {'EXIT', Pid, R}, State) when R /= wait_for_tables_timeout ->
13061308
end;
13071309

13081310
handle_info({From, get_state}, State) ->
1309-
From ! {?SERVER_NAME, State},
1311+
From ! {?SERVER_NAME, From, State},
13101312
noreply(State);
13111313

13121314
%% No real need for buffering
@@ -1860,12 +1862,14 @@ get_info(Timeout) ->
18601862
undefined ->
18611863
{timeout, Timeout};
18621864
Pid ->
1863-
Pid ! {self(), get_state},
1865+
Alias = alias([reply]),
1866+
Pid ! {Alias, get_state},
18641867
receive
1865-
{?SERVER_NAME, State = #state{loader_queue=LQ,late_loader_queue=LLQ}} ->
1868+
{?SERVER_NAME, Alias, State = #state{loader_queue=LQ,late_loader_queue=LLQ}} ->
18661869
{info,State#state{loader_queue=gb_trees:to_list(LQ),
18671870
late_loader_queue=gb_trees:to_list(LLQ)}}
18681871
after Timeout ->
1872+
?unalias_and_flush_msg(Alias, {?SERVER_NAME, Alias, _}),
18691873
{timeout, Timeout}
18701874
end
18711875
end.
@@ -1875,11 +1879,13 @@ get_workers(Timeout) ->
18751879
undefined ->
18761880
{timeout, Timeout};
18771881
Pid ->
1878-
Pid ! {self(), get_state},
1882+
Alias = alias([reply]),
1883+
Pid ! {Alias, get_state},
18791884
receive
1880-
{?SERVER_NAME, State = #state{}} ->
1885+
{?SERVER_NAME, Alias, State = #state{}} ->
18811886
{workers, get_loaders(State), get_senders(State), State#state.dumper_pid}
18821887
after Timeout ->
1888+
?unalias_and_flush_msg(Alias, {?SERVER_NAME, Alias, _}),
18831889
{timeout, Timeout}
18841890
end
18851891
end.

lib/mnesia/src/mnesia_locker.erl

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

11281128
get_held_locks() ->
1129-
?MODULE ! {get_table, self(), mnesia_held_locks},
1130-
Locks = receive {mnesia_held_locks, Ls} -> Ls after 5000 -> [] end,
1129+
Alias = alias([reply]),
1130+
?MODULE ! {get_table, Alias, mnesia_held_locks},
1131+
Locks = receive
1132+
{mnesia_held_locks, Ls} ->
1133+
Ls
1134+
after 5000 ->
1135+
?unalias_and_flush_msg(Alias, {mnesia_held_locks, _}),
1136+
[]
1137+
end,
11311138
rewrite_locks(Locks, []).
11321139

11331140
%% Mnesia internal usage only
@@ -1148,8 +1155,15 @@ rewrite_locks([], Acc) ->
11481155
lists:reverse(Acc).
11491156

11501157
get_lock_queue() ->
1151-
?MODULE ! {get_table, self(), mnesia_lock_queue},
1152-
Q = receive {mnesia_lock_queue, Locks} -> Locks after 5000 -> [] end,
1158+
Alias = alias([reply]),
1159+
?MODULE ! {get_table, Alias, mnesia_lock_queue},
1160+
Q = receive
1161+
{mnesia_lock_queue, Locks} ->
1162+
Locks
1163+
after 5000 ->
1164+
?unalias_and_flush_msg(Alias, {mnesia_lock_queue, _}),
1165+
[]
1166+
end,
11531167
[{Oid, Op, Pid, Tid, WFT} || {queue, Oid, Tid, Op, Pid, WFT} <- Q].
11541168

11551169
do_stop() ->

lib/mnesia/src/mnesia_tm.erl

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1108,8 +1108,12 @@ intercept_best_friend([{stop,Fun} | R],Ignore) ->
11081108
?CATCH(Fun()),
11091109
intercept_best_friend(R,Ignore);
11101110
intercept_best_friend([Pid | R],false) ->
1111-
Pid ! {activity_ended, undefined, self()},
1111+
Alias = alias([reply]),
1112+
Pid ! {activity_ended, undefined, Alias},
11121113
wait_for_best_friend(Pid, 0),
1114+
unalias(Alias),
1115+
?flush_msg({activity_ended, _, Pid}),
1116+
?flush_msg({'EXIT', Pid, _}),
11131117
intercept_best_friend(R,true);
11141118
intercept_best_friend([_|R],true) ->
11151119
intercept_best_friend(R,true).
@@ -2049,8 +2053,9 @@ sync_send_dirty(Tid, [Head | Tail], Tab, WaitFor) ->
20492053
Res = do_dirty(Tid, Head),
20502054
{WF, Res};
20512055
true ->
2052-
{?MODULE, Node} ! {self(), {sync_dirty, Tid, Head, Tab}},
2053-
sync_send_dirty(Tid, Tail, Tab, [Node | WaitFor])
2056+
Alias = alias([reply]),
2057+
{?MODULE, Node} ! {Alias, {sync_dirty, Tid, Head, Tab}},
2058+
sync_send_dirty(Tid, Tail, Tab, [{Node, Alias} | WaitFor])
20542059
end;
20552060
sync_send_dirty(_Tid, [], _Tab, WaitFor) ->
20562061
{WaitFor, {'EXIT', {aborted, {node_not_running, WaitFor}}}}.
@@ -2068,18 +2073,27 @@ async_send_dirty(Tid, [Head | Tail], Tab, ReadNode, WaitFor, Res) ->
20682073
NewRes = do_dirty(Tid, Head),
20692074
async_send_dirty(Tid, Tail, Tab, ReadNode, WaitFor, NewRes);
20702075
ReadNode == Node ->
2071-
{?MODULE, Node} ! {self(), {sync_dirty, Tid, Head, Tab}},
2076+
Alias = alias([reply]),
2077+
{?MODULE, Node} ! {Alias, {sync_dirty, Tid, Head, Tab}},
20722078
NewRes = {'EXIT', {aborted, {node_not_running, Node}}},
2073-
async_send_dirty(Tid, Tail, Tab, ReadNode, [Node | WaitFor], NewRes);
2079+
async_send_dirty(Tid, Tail, Tab, ReadNode, [{Node, Alias} | WaitFor], NewRes);
20742080
true ->
20752081
{?MODULE, Node} ! {self(), {async_dirty, Tid, Head, Tab}},
20762082
async_send_dirty(Tid, Tail, Tab, ReadNode, WaitFor, Res)
20772083
end;
20782084
async_send_dirty(_Tid, [], _Tab, _ReadNode, WaitFor, Res) ->
20792085
{WaitFor, Res}.
20802086

2081-
rec_dirty([Node | Tail], Res) when Node /= node() ->
2082-
NewRes = get_dirty_reply(Node, Res),
2087+
rec_dirty([{Node, Alias} | Tail], Res) when Node /= node() ->
2088+
NewRes =
2089+
try
2090+
get_dirty_reply(Node, Res)
2091+
after
2092+
unalias(Alias),
2093+
?flush_msg({?MODULE, Node, {'EXIT', _}}),
2094+
?flush_msg({?MODULE, Node, {dirty_res, _}}),
2095+
?flush_msg({mnesia_down, Node})
2096+
end,
20832097
rec_dirty(Tail, NewRes);
20842098
rec_dirty([], Res) ->
20852099
Res.
@@ -2203,11 +2217,13 @@ get_info(Timeout) ->
22032217
undefined ->
22042218
{timeout, Timeout};
22052219
Pid ->
2206-
Pid ! {self(), info},
2220+
Alias = alias([reply]),
2221+
Pid ! {Alias, info},
22072222
receive
22082223
{?MODULE, _, {info, Part, Coord}} ->
22092224
{info, Part, Coord}
22102225
after Timeout ->
2226+
?unalias_and_flush_msg(Alias, {?MODULE, _, {info, _, _}}),
22112227
{timeout, Timeout}
22122228
end
22132229
end.

0 commit comments

Comments
 (0)