aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2011-09-27 08:51:51 +0200
committerBjörn Gustavsson <[email protected]>2011-09-27 09:50:10 +0200
commitbc4362edacedb40c6edb9e855aa234c066b8292f (patch)
tree769589b666af1003c0450d75674072654cf3e86b /lib
parente423e12e8ad87348ca6c583b0ebdbe5de2aefc6f (diff)
downloadotp-bc4362edacedb40c6edb9e855aa234c066b8292f.tar.gz
otp-bc4362edacedb40c6edb9e855aa234c066b8292f.tar.bz2
otp-bc4362edacedb40c6edb9e855aa234c066b8292f.zip
beam_lib: Handle rare race in the crypto key server functionality
In rare circumstances, there can be a race when the crypto key server is started by beam_lib:crypto_key_fun/1 shortly after stopping it using beam_lib:clear_crypto_key_fun/0. The race occurs because the crypto key server first sends back the reply to the calling process, then terminates. (The race is probably more likely to happen on CPUs with hyper threading.)
Diffstat (limited to 'lib')
-rw-r--r--lib/stdlib/src/beam_lib.erl14
-rw-r--r--lib/stdlib/test/beam_lib_SUITE.erl10
2 files changed, 19 insertions, 5 deletions
diff --git a/lib/stdlib/src/beam_lib.erl b/lib/stdlib/src/beam_lib.erl
index d9c645d787..fdfbb2e998 100644
--- a/lib/stdlib/src/beam_lib.erl
+++ b/lib/stdlib/src/beam_lib.erl
@@ -893,13 +893,17 @@ call_crypto_server(Req) ->
gen_server:call(?CRYPTO_KEY_SERVER, Req, infinity)
catch
exit:{noproc,_} ->
- start_crypto_server(),
- erlang:yield(),
- call_crypto_server(Req)
+ %% Not started.
+ call_crypto_server_1(Req);
+ exit:{normal,_} ->
+ %% The process finished just as we called it.
+ call_crypto_server_1(Req)
end.
-start_crypto_server() ->
- gen_server:start({local,?CRYPTO_KEY_SERVER}, ?MODULE, [], []).
+call_crypto_server_1(Req) ->
+ gen_server:start({local,?CRYPTO_KEY_SERVER}, ?MODULE, [], []),
+ erlang:yield(),
+ call_crypto_server(Req).
-spec init([]) -> {'ok', #state{}}.
diff --git a/lib/stdlib/test/beam_lib_SUITE.erl b/lib/stdlib/test/beam_lib_SUITE.erl
index 91fff3cee4..27520a5c88 100644
--- a/lib/stdlib/test/beam_lib_SUITE.erl
+++ b/lib/stdlib/test/beam_lib_SUITE.erl
@@ -571,8 +571,18 @@ do_encrypted_abstr(Beam, Key) ->
?line {ok,{simple,[{"Abst",Abst}]}} = beam_lib:chunks(Beam, ["Abst"]),
?line {ok,cleared} = beam_lib:clear_crypto_key_fun(),
+
+ %% Try to force a stop/start race.
+ ?line start_stop_race(10000),
+
ok.
+start_stop_race(0) ->
+ ok;
+start_stop_race(N) ->
+ {error,_} = beam_lib:crypto_key_fun(bad_fun),
+ undefined = beam_lib:clear_crypto_key_fun(),
+ start_stop_race(N-1).
bad_fun(F) ->
{error,E} = beam_lib:crypto_key_fun(F),