aboutsummaryrefslogtreecommitdiffstats
path: root/lib/kernel/test
diff options
context:
space:
mode:
authorRickard Green <[email protected]>2010-03-09 12:00:00 +0100
committerBjörn Gustavsson <[email protected]>2010-08-20 08:45:26 +0200
commit075a7ffcabb8c8a4c5ce06c11155403f1967a670 (patch)
treeb64eae7d1fd956e5ea790046cebed8651e445891 /lib/kernel/test
parent2fe5bce0ff7998ed4dcc833a4ae9b4b5feb450e2 (diff)
downloadotp-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')
-rw-r--r--lib/kernel/test/os_SUITE.erl46
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