diff options
author | Rickard Green <[email protected]> | 2010-03-09 12:00:00 +0100 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2010-08-20 08:45:26 +0200 |
commit | 075a7ffcabb8c8a4c5ce06c11155403f1967a670 (patch) | |
tree | b64eae7d1fd956e5ea790046cebed8651e445891 /lib/kernel/test/os_SUITE.erl | |
parent | 2fe5bce0ff7998ed4dcc833a4ae9b4b5feb450e2 (diff) | |
download | otp-075a7ffcabb8c8a4c5ce06c11155403f1967a670.tar.gz otp-075a7ffcabb8c8a4c5ce06c11155403f1967a670.tar.bz2 otp-075a7ffcabb8c8a4c5ce06c11155403f1967a670.zip |
kernel: Patch 1109
OTP-8502 A race condition in <c>os:cmd/1</c> could cause the caller to
get stuck in <c>os:cmd/1</c> forever.
Diffstat (limited to 'lib/kernel/test/os_SUITE.erl')
-rw-r--r-- | lib/kernel/test/os_SUITE.erl | 46 |
1 files changed, 44 insertions, 2 deletions
diff --git a/lib/kernel/test/os_SUITE.erl b/lib/kernel/test/os_SUITE.erl index 1673b33010..6a3534b094 100644 --- a/lib/kernel/test/os_SUITE.erl +++ b/lib/kernel/test/os_SUITE.erl @@ -20,13 +20,13 @@ -export([all/1]). -export([space_in_cwd/1, quoting/1, space_in_name/1, bad_command/1, - find_executable/1, unix_comment_in_command/1]). + find_executable/1, unix_comment_in_command/1, evil/1]). -include("test_server.hrl"). all(suite) -> [space_in_cwd, quoting, space_in_name, bad_command, find_executable, - unix_comment_in_command]. + unix_comment_in_command, evil]. space_in_cwd(doc) -> "Test that executing a command in a current working directory " @@ -186,6 +186,48 @@ unix_comment_in_command(Config) when is_list(Config) -> ?line test_server:timetrap_cancel(Dog), ok. +-define(EVIL_PROCS, 100). +-define(EVIL_LOOPS, 100). +-define(PORT_CREATOR, os_cmd_port_creator). +evil(Config) when is_list(Config) -> + Dog = test_server:timetrap(test_server:minutes(5)), + Parent = self(), + Ps = lists:map(fun (N) -> + spawn_link(fun () -> + evil_loop(Parent, ?EVIL_LOOPS,N) + end) + end, lists:seq(1, ?EVIL_PROCS)), + Devil = spawn(fun () -> devil(hd(Ps), hd(lists:reverse(Ps))) end), + lists:foreach(fun (P) -> receive {P, done} -> ok end end, Ps), + exit(Devil, kill), + test_server:timetrap_cancel(Dog), + ok. + +devil(P1, P2) -> + erlang:display({?PORT_CREATOR, whereis(?PORT_CREATOR)}), + (catch ?PORT_CREATOR ! lists:seq(1,1000000)), + (catch ?PORT_CREATOR ! lists:seq(1,666)), + (catch ?PORT_CREATOR ! grrrrrrrrrrrrrrrr), + (catch ?PORT_CREATOR ! {'EXIT', P1, buhuuu}), + (catch ?PORT_CREATOR ! {'EXIT', hd(erlang:ports()), buhuuu}), + (catch ?PORT_CREATOR ! {'EXIT', P2, arggggggg}), + receive after 500 -> ok end, + (catch exit(whereis(?PORT_CREATOR), kill)), + (catch ?PORT_CREATOR ! ">8|"), + receive after 500 -> ok end, + (catch exit(whereis(?PORT_CREATOR), diiiiiiiiiiiiiiiiiiiie)), + receive after 100 -> ok end, + devil(P1, P2). + +evil_loop(Parent, Loops, N) -> + Res = integer_to_list(N), + evil_loop(Parent, Loops, Res, "echo " ++ Res). + +evil_loop(Parent, 0, _Res, _Cmd) -> + Parent ! {self(), done}; +evil_loop(Parent, Loops, Res, Cmd) -> + comp(Res, os:cmd(Cmd)), + evil_loop(Parent, Loops-1, Res, Cmd). comp(Expected, Got) -> case strip_nl(Got) of |