aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/test/port_SUITE.erl
diff options
context:
space:
mode:
authorLukas Larsson <[email protected]>2015-12-15 10:10:10 +0100
committerLukas Larsson <[email protected]>2015-12-15 10:21:40 +0100
commit9083bc7e2172937296b7e8fbe09ed595c6893f08 (patch)
treeb3b4255af12bf6cc023ee7a47bcf5ae5ae115077 /erts/emulator/test/port_SUITE.erl
parentd7cd5ee8a34d289fbc91627a3f096a870bf70393 (diff)
parent4b1b3bf6c62f8208b2eea506c9dac1504df6e916 (diff)
downloadotp-9083bc7e2172937296b7e8fbe09ed595c6893f08.tar.gz
otp-9083bc7e2172937296b7e8fbe09ed595c6893f08.tar.bz2
otp-9083bc7e2172937296b7e8fbe09ed595c6893f08.zip
Merge branch 'lukas/erts/forker'
* lukas/erts/forker: (28 commits) erts: Never abort in the forked child erts: Mend ASSERT makro for erl_child_setup erts: Allow enomem failures in port_SUITE erts: iter_port sleep longer on freebsd erts: Allow one dangling fd if there is a gethost port erts: Only use forker StackAck on freebsd erts: It is not possible to exit the forker driver erts: Add forker StartAck for port start flowcontrol erts: Fix large open_port arg segfault for win32 erts: Fix memory leak at async open port kernel: Remove cmd server for unix os:cmd erts: Add testcase for huge port environment erts: Move os_pid to port hash to child setup erts: Handle all EINTR and EAGAIN cases in child setup erts: Make child_setup work with large environments erts: Fix forker driver ifdefs for win32 erts: Fix uds socket handling for os x erts: Fix dereferencing of unaligned integer for sparc erts: Flatten too long io vectors in uds write erts: Add fd count test for spawn_driver ... Conflicts: erts/emulator/beam/erl_node_tables.c erts/preloaded/src/erts_internal.erl
Diffstat (limited to 'erts/emulator/test/port_SUITE.erl')
-rw-r--r--erts/emulator/test/port_SUITE.erl126
1 files changed, 106 insertions, 20 deletions
diff --git a/erts/emulator/test/port_SUITE.erl b/erts/emulator/test/port_SUITE.erl
index b42e02a1e1..ff75ee86d6 100644
--- a/erts/emulator/test/port_SUITE.erl
+++ b/erts/emulator/test/port_SUITE.erl
@@ -82,10 +82,11 @@
mul_basic/1, mul_slow_writes/1,
dying_port/1, port_program_with_path/1,
open_input_file_port/1, open_output_file_port/1,
+ count_fds/1,
iter_max_ports/1, eof/1, input_only/1, output_only/1,
name1/1,
t_binary/1, parallell/1, t_exit/1,
- env/1, bad_env/1, cd/1, exit_status/1,
+ env/1, huge_env/1, bad_env/1, cd/1, exit_status/1,
tps_16_bytes/1, tps_1K/1, line/1, stderr_to_stdout/1,
otp_3906/1, otp_4389/1, win_massive/1, win_massive_client/1,
mix_up_ports/1, otp_5112/1, otp_5119/1, otp_6224/1,
@@ -111,8 +112,8 @@ all() ->
bad_packet, bad_port_messages, {group, options},
{group, multiple_packets}, parallell, dying_port,
port_program_with_path, open_input_file_port,
- open_output_file_port, name1, env, bad_env, cd,
- exit_status, iter_max_ports, t_exit, {group, tps}, line,
+ open_output_file_port, name1, env, huge_env, bad_env, cd,
+ exit_status, iter_max_ports, count_fds, t_exit, {group, tps}, line,
stderr_to_stdout, otp_3906, otp_4389, win_massive,
mix_up_ports, otp_5112, otp_5119,
exit_status_multi_scheduling_block, ports, spawn_driver,
@@ -385,27 +386,33 @@ input_only(Config) when is_list(Config) ->
output_only(Config) when is_list(Config) ->
Dog = test_server:timetrap(test_server:seconds(100)),
Dir = ?config(priv_dir, Config),
+
+ %% First we test that the port program gets the data
Filename = filename:join(Dir, "output_only_stream"),
- output_and_verify(Config, Filename, "-h0",
- random_packet(35777, "echo")),
+ Data = random_packet(35777, "echo"),
+ output_and_verify(Config, ["-h0 -o", Filename], Data),
+ Wait_time = 500,
+ test_server:sleep(Wait_time),
+ {ok, Written} = file:read_file(Filename),
+ Data = binary_to_list(Written),
+
+ %% Then we test that any writes to stdout from
+ %% the port program is not sent to erlang
+ output_and_verify(Config, ["-h0"], Data),
+
test_server:timetrap_cancel(Dog),
ok.
-output_and_verify(Config, Filename, Options, Data) ->
+output_and_verify(Config, Options, Data) ->
PortTest = port_test(Config),
- Command = lists:concat([PortTest, " ",
- Options, " -o", Filename]),
+ Command = lists:concat([PortTest, " " | Options]),
Port = open_port({spawn, Command}, [out]),
Port ! {self(), {command, Data}},
Port ! {self(), close},
receive
- {Port, closed} -> ok
- end,
- Wait_time = 500,
- test_server:sleep(Wait_time),
- {ok, Written} = file:read_file(Filename),
- Data = binary_to_list(Written),
- ok.
+ {Port, closed} -> ok;
+ Msg -> ct:fail({received_unexpected_message, Msg})
+ end.
%% Test that receiving several packages written in the same
%% write operation works.
@@ -610,6 +617,38 @@ open_output_file_port(Config) when is_list(Config) ->
test_server:timetrap_cancel(Dog),
ok.
+%% Tests that all appropriate fd's have been closed in the port program
+count_fds(suite) -> [];
+count_fds(Config) when is_list(Config) ->
+ case os:type() of
+ {unix, _} ->
+ PrivDir = proplists:get_value(priv_dir, Config),
+ Filename = filename:join(PrivDir, "my_fd_counter"),
+
+ RunTest = fun(PortOpts) ->
+ PortTest = port_test(Config),
+ Command = lists:concat([PortTest, " -n -f -o", Filename]),
+ Port = open_port({spawn, Command}, PortOpts),
+ Port ! {self(), close},
+ receive
+ {Port, closed} -> ok
+ end,
+ test_server:sleep(500),
+ {ok, Written} = file:read_file(Filename),
+ Written
+ end,
+ <<4:32/native>> = RunTest([out, nouse_stdio]),
+ <<4:32/native>> = RunTest([in, nouse_stdio]),
+ <<5:32/native>> = RunTest([in, out, nouse_stdio]),
+ <<3:32/native>> = RunTest([out, use_stdio]),
+ <<3:32/native>> = RunTest([in, use_stdio]),
+ <<3:32/native>> = RunTest([in, out, use_stdio]),
+ <<3:32/native>> = RunTest([in, out, use_stdio, stderr_to_stdout]),
+ <<3:32/native>> = RunTest([out, use_stdio, stderr_to_stdout]);
+ _ ->
+ {skip, "Skipped on windows"}
+ end.
+
%%
%% Open as many ports as possible. Do this several times and check
%% that we get the same number of ports every time.
@@ -680,7 +719,16 @@ close_ports([]) ->
ok.
open_ports(Name, Settings) ->
- test_server:sleep(5),
+ case os:type() of
+ {unix, freebsd} ->
+ %% FreeBsd has issues with sendmsg/recvmsg in fork
+ %% implementation and we therefor have to spawn
+ %% slower to make sure that we always hit the same
+ %% make roof.
+ test_server:sleep(10);
+ _ ->
+ test_server:sleep(5)
+ end,
case catch open_port(Name, Settings) of
P when is_port(P) ->
[P| open_ports(Name, Settings)];
@@ -923,6 +971,40 @@ try_bad_env(Env) ->
error:badarg -> ok
end.
+%% Test that we can handle a very very large environment gracefully.
+huge_env(Config) when is_list(Config) ->
+ Vars = case os:type() of
+ {win32,_} -> 500;
+ _ ->
+ %% We create a huge environment,
+ %% 20000 variables is about 25MB
+ %% which seems to be the limit on Linux.
+ 20000
+ end,
+ Env = [{[$a + I div (25*25*25*25) rem 25,
+ $a + I div (25*25*25) rem 25,
+ $a + I div (25*25) rem 25,
+ $a+I div 25 rem 25, $a+I rem 25],
+ lists:duplicate(100,$a+I rem 25)}
+ || I <- lists:seq(1,Vars)],
+ try erlang:open_port({spawn,"ls"},[exit_status, {env, Env}]) of
+ P ->
+ receive
+ {P, {exit_status,N}} = M ->
+ %% We test that the exit status is an integer, this means
+ %% that the child program has started. If we get an atom
+ %% something went wrong in the driver which is not ok.
+ ct:log("Got ~p",[M]),
+ true = is_integer(N)
+ end
+ catch E:R ->
+ %% Have to catch the error here, as printing the stackdump
+ %% in the ct log is way to heavy for some test machines.
+ ct:fail("Open port failed ~p:~p",[E,R])
+ end.
+
+
+
%% 'cd' option
%% (Can perhaps be made smaller by calling the other utility functions
%% in this module.)
@@ -1228,13 +1310,15 @@ otp_4389(Config) when is_list(Config) ->
{P,{exit_status,_}} ->
TCR ! {self(),ok};
{'EXIT',_,{R2,_}} when R2 == emfile;
- R2 == eagain ->
+ R2 == eagain;
+ R2 == enomem ->
TCR ! {self(),ok};
Err2 ->
TCR ! {self(),{msg,Err2}}
end;
{'EXIT',{R1,_}} when R1 == emfile;
- R1 == eagain ->
+ R1 == eagain;
+ R1 == enomem ->
TCR ! {self(),ok};
Err1 ->
TCR ! {self(), {open_port,Err1}}
@@ -1840,10 +1924,12 @@ exit_status_msb_test(Config, SleepSecs) when is_list(Config) ->
{Prt,
erlang:system_info(scheduler_id)};
{'EXIT', {Err, _}} when Err == eagain;
- Err == emfile ->
+ Err == emfile;
+ Err == enomem ->
noop;
{'EXIT', Err} when Err == eagain;
- Err == emfile ->
+ Err == emfile;
+ Err == enomem ->
noop;
Error ->
?t:fail(Error)