diff options
author | Anthony Ramine <[email protected]> | 2015-03-12 16:01:33 +0100 |
---|---|---|
committer | Anthony Ramine <[email protected]> | 2015-03-18 12:04:22 +0100 |
commit | 6f9c07ae2694a2dc1f721fd10af22b8813d15bc1 (patch) | |
tree | 4d1725130a183eb0eee86bbd39955ac39b8124f8 | |
parent | 07abc92d5c763cee81bf69695e35a658ddc961dc (diff) | |
download | otp-6f9c07ae2694a2dc1f721fd10af22b8813d15bc1.tar.gz otp-6f9c07ae2694a2dc1f721fd10af22b8813d15bc1.tar.bz2 otp-6f9c07ae2694a2dc1f721fd10af22b8813d15bc1.zip |
Fix a race condition when calling port_info/1
This variable hold the values returned by erlang:port_info/1 and
shouldn't be static.
Reported-by: Heinz Nikolaus Gies
-rw-r--r-- | erts/emulator/beam/io.c | 2 | ||||
-rw-r--r-- | erts/emulator/test/port_bif_SUITE.erl | 27 |
2 files changed, 26 insertions, 3 deletions
diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c index 012a7d1a4b..a950998c13 100644 --- a/erts/emulator/beam/io.c +++ b/erts/emulator/beam/io.c @@ -4484,7 +4484,7 @@ make_port_info_term(Eterm **hpp_start, int len; int start; static Eterm item[] = ERTS_PORT_INFO_1_ITEMS; - static Eterm value[sizeof(item)/sizeof(item[0])]; + Eterm value[sizeof(item)/sizeof(item[0])]; start = 0; len = sizeof(item)/sizeof(item[0]); diff --git a/erts/emulator/test/port_bif_SUITE.erl b/erts/emulator/test/port_bif_SUITE.erl index f439867e9c..0c5b09d45a 100644 --- a/erts/emulator/test/port_bif_SUITE.erl +++ b/erts/emulator/test/port_bif_SUITE.erl @@ -24,7 +24,7 @@ init_per_group/2,end_per_group/2, command/1, command_e_1/1, command_e_2/1, command_e_3/1, command_e_4/1, port_info1/1, port_info2/1, - port_info_os_pid/1, + port_info_os_pid/1, port_info_race/1, connect/1, control/1, echo_to_busy/1]). -export([do_command_e_1/1, do_command_e_2/1, do_command_e_4/1]). @@ -42,7 +42,8 @@ all() -> groups() -> [{command_e, [], [command_e_1, command_e_2, command_e_3, command_e_4]}, - {port_info, [], [port_info1, port_info2, port_info_os_pid]}]. + {port_info, [], + [port_info1, port_info2, port_info_os_pid, port_info_race]}]. init_per_suite(Config) -> Config. @@ -254,6 +255,28 @@ do_port_info_os_pid() -> true = erlang:port_close(P), ok. +port_info_race(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + Program = filename:join(DataDir, "port_test"), + Top = self(), + P1 = open_port({spawn,Program}, [{packet,1}]), + P2 = open_port({spawn,Program}, [{packet,1}]), + Info1 = erlang:port_info(P1), + Info2 = erlang:port_info(P2), + F = fun Loop(Port, _, 0) -> + Top ! {ok,Port}; + Loop(Port, Info, N) -> + Info = erlang:port_info(Port), + Loop(Port, Info, N - 1) + end, + spawn_link(fun () -> F(P1, Info1, 1000) end), + spawn_link(fun () -> F(P2, Info2, 1000) end), + receive {ok,P1} -> ok end, + receive {ok,P2} -> ok end, + true = erlang:port_close(P1), + true = erlang:port_close(P2), + ok. + output_test(_, _, Input, Output) when Output > 16#1fffffff -> io:format("~p bytes received\n", [Input]); output_test(P, Bin, Input0, Output0) -> |