From 04c8809142306b8b2c617b1e0d8c005b2099be48 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Wed, 26 Nov 2014 11:55:26 +0100 Subject: Sort keys before generating This has to be done in order to consistently generate the same file so that we do not get rebuilds all the time. --- erts/emulator/utils/make_compiler_flags | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erts/emulator/utils/make_compiler_flags b/erts/emulator/utils/make_compiler_flags index cebe8cd0c5..ca1bc47113 100755 --- a/erts/emulator/utils/make_compiler_flags +++ b/erts/emulator/utils/make_compiler_flags @@ -70,7 +70,7 @@ my($prog) = $prog[$#prog]; print "/* Warning: Do not edit this file.\n"; print " Auto-generated by '$prog'.*/\n"; -foreach(keys %constants) { +foreach (sort(keys %constants)) { print "const char* erts_build_flags_$_ = \"$constants{$_}\";\n" } -- cgit v1.2.3 From 57d819805eb032605c64a0128dd70955d7aa085a Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Tue, 30 Sep 2014 16:55:06 +0200 Subject: erts: Fix erlang:port_set_data/2 for non immediate data hsize field was not set leading to VM crash --- erts/emulator/beam/erl_bif_port.c | 1 + 1 file changed, 1 insertion(+) diff --git a/erts/emulator/beam/erl_bif_port.c b/erts/emulator/beam/erl_bif_port.c index 3cd53ef65d..f4ab8592ae 100644 --- a/erts/emulator/beam/erl_bif_port.c +++ b/erts/emulator/beam/erl_bif_port.c @@ -554,6 +554,7 @@ BIF_RETTYPE port_set_data_2(BIF_ALIST_2) hp = &pdhp->heap[0]; pdhp->off_heap.first = NULL; pdhp->off_heap.overhead = 0; + pdhp->hsize = hsize; pdhp->data = copy_struct(BIF_ARG_2, hsize, &hp, &pdhp->off_heap); data = (erts_aint_t) pdhp; ASSERT((data & 0x3) == 0); -- cgit v1.2.3 From 51d2888163b230836c16944f54ca3a3840a73ad2 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Tue, 30 Sep 2014 17:00:37 +0200 Subject: erts: Fix race between port_set_data, port_get_data and port termination Always update prt->data with atomic xchg-op. Check for NULL data to detect racing port terminator. Use NULL, as THE_NON_VALUE can be a valid pointer on debug VM. --- erts/emulator/beam/erl_bif_port.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/erts/emulator/beam/erl_bif_port.c b/erts/emulator/beam/erl_bif_port.c index f4ab8592ae..2464da6d24 100644 --- a/erts/emulator/beam/erl_bif_port.c +++ b/erts/emulator/beam/erl_bif_port.c @@ -493,8 +493,8 @@ void erts_cleanup_port_data(Port *prt) { ASSERT(erts_atomic32_read_nob(&prt->state) & ERTS_PORT_SFLGS_INVALID_LOOKUP); - cleanup_old_port_data(erts_smp_atomic_read_nob(&prt->data)); - erts_smp_atomic_set_nob(&prt->data, (erts_aint_t) THE_NON_VALUE); + cleanup_old_port_data(erts_smp_atomic_xchg_nob(&prt->data, + (erts_aint_t) NULL)); } Uint @@ -562,8 +562,14 @@ BIF_RETTYPE port_set_data_2(BIF_ALIST_2) data = erts_smp_atomic_xchg_wb(&prt->data, data); + if (data == (erts_aint_t)NULL) { + /* Port terminated by racing thread */ + data = erts_smp_atomic_xchg_wb(&prt->data, data); + ASSERT(data != (erts_aint_t)NULL); + cleanup_old_port_data(data); + BIF_ERROR(BIF_P, BADARG); + } cleanup_old_port_data(data); - BIF_RET(am_true); } @@ -582,6 +588,8 @@ BIF_RETTYPE port_get_data_1(BIF_ALIST_1) BIF_ERROR(BIF_P, BADARG); data = erts_smp_atomic_read_ddrb(&prt->data); + if (data == (erts_aint_t)NULL) + BIF_ERROR(BIF_P, BADARG); /* Port terminated by racing thread */ if ((data & 0x3) != 0) { res = (Eterm) (UWord) data; -- cgit v1.2.3 From 87c92cbef17fa3c5b4070b98afa551de006ae2aa Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Tue, 30 Sep 2014 20:52:00 +0200 Subject: erts: Add test case for port_set_data and port_get_data --- erts/emulator/test/port_SUITE.erl | 51 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/erts/emulator/test/port_SUITE.erl b/erts/emulator/test/port_SUITE.erl index fcd4457c34..78d76ccb64 100644 --- a/erts/emulator/test/port_SUITE.erl +++ b/erts/emulator/test/port_SUITE.erl @@ -90,6 +90,7 @@ mix_up_ports/1, otp_5112/1, otp_5119/1, otp_6224/1, exit_status_multi_scheduling_block/1, ports/1, spawn_driver/1, spawn_executable/1, close_deaf_port/1, + port_setget_data/1, unregister_name/1, parallelism_option/1]). -export([do_iter_max_ports/2]). @@ -115,6 +116,7 @@ all() -> mix_up_ports, otp_5112, otp_5119, exit_status_multi_scheduling_block, ports, spawn_driver, spawn_executable, close_deaf_port, unregister_name, + port_setget_data, parallelism_option]. groups() -> @@ -2287,6 +2289,55 @@ close_deaf_port_1(N, Cmd) -> {comment, "Could not spawn more than " ++ integer_to_list(N) ++ " OS processes."} end. +%% Test undocumented port_set_data/2 and port_get_data/1 +%% Hammer from multiple processes a while +%% and then abrubtly close the port (OTP-12208). +port_setget_data(Config) when is_list(Config) -> + ok = load_driver(?config(data_dir, Config), "echo_drv"), + Port = erlang:open_port({spawn_driver, "echo_drv"}, []), + + NSched = erlang:system_info(schedulers_online), + PRs = lists:map(fun(I) -> + spawn_opt(fun() -> port_setget_data_hammer(Port,1) end, + [monitor, {scheduler, I rem NSched}]) + end, + lists:seq(1,10)), + receive after 100 -> ok end, + Papa = self(), + lists:foreach(fun({Pid,_}) -> Pid ! {Papa,prepare_for_close} end, PRs), + lists:foreach(fun({Pid,_}) -> + receive {Pid,prepare_for_close} -> ok end + end, + PRs), + port_close(Port), + lists:foreach(fun({Pid,Ref}) -> + receive {'DOWN', Ref, process, Pid, normal} -> ok end + end, + PRs), + ok. + +port_setget_data_hammer(Port, N) -> + Rand = random:uniform(3), + try case Rand of + 1 -> true = erlang:port_set_data(Port, atom); + 2 -> true = erlang:port_set_data(Port, {1,2,3}); + 3 -> erlang:port_get_data(Port) + end + catch + error:badarg -> + true = get(prepare_for_close), + io:format("~p did ~p rounds before port closed\n", [self(), N]), + exit(normal) + end, + receive {Papa, prepare_for_close} -> + put(prepare_for_close, true), + Papa ! {self(),prepare_for_close} + after 0 -> + ok + end, + port_setget_data_hammer(Port, N+1). + + wait_until(Fun) -> case catch Fun() of true -> -- cgit v1.2.3 From 3d90589d81e6569588fc197676c4d94c59e84f8e Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Thu, 2 Oct 2014 21:40:28 +0200 Subject: erts: Mend port_set_data with non-immed data for halfword VM --- erts/emulator/beam/erl_alloc.types | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erts/emulator/beam/erl_alloc.types b/erts/emulator/beam/erl_alloc.types index bb5eba80be..64f424d99a 100644 --- a/erts/emulator/beam/erl_alloc.types +++ b/erts/emulator/beam/erl_alloc.types @@ -267,7 +267,6 @@ type CODE_IX_LOCK_Q SHORT_LIVED SYSTEM code_ix_lock_q type PROC_INTERVAL LONG_LIVED SYSTEM process_interval type BUSY_CALLER_TAB SHORT_LIVED SYSTEM busy_caller_table type BUSY_CALLER SHORT_LIVED SYSTEM busy_caller -type PORT_DATA_HEAP STANDARD SYSTEM port_data_heap +if threads_no_smp # Need thread safe allocs, but std_alloc and fix_alloc are not; @@ -361,6 +360,7 @@ type NLINK_SH STANDARD_LOW PROCESSES nlink_sh type AINFO_REQ STANDARD_LOW SYSTEM alloc_info_request type SCHED_WTIME_REQ STANDARD_LOW SYSTEM sched_wall_time_request type GC_INFO_REQ STANDARD_LOW SYSTEM gc_info_request +type PORT_DATA_HEAP STANDARD_LOW SYSTEM port_data_heap +else # "fullword" @@ -379,6 +379,7 @@ type NLINK_SH FIXED_SIZE PROCESSES nlink_sh type AINFO_REQ SHORT_LIVED SYSTEM alloc_info_request type SCHED_WTIME_REQ SHORT_LIVED SYSTEM sched_wall_time_request type GC_INFO_REQ SHORT_LIVED SYSTEM gc_info_request +type PORT_DATA_HEAP STANDARD SYSTEM port_data_heap +endif -- cgit v1.2.3 From 25bb9b1ab01aeb23aee75730ba4cd3b12a19988b Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Tue, 25 Nov 2014 14:33:04 +0100 Subject: erts: Fix port data memory allocation bug for non-immediate port data >= sizeof(Eterm)*2 words. --- erts/emulator/beam/erl_bif_port.c | 6 +++--- erts/emulator/test/port_SUITE.erl | 22 ++++++++++++++-------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/erts/emulator/beam/erl_bif_port.c b/erts/emulator/beam/erl_bif_port.c index 2464da6d24..ab473c6a08 100644 --- a/erts/emulator/beam/erl_bif_port.c +++ b/erts/emulator/beam/erl_bif_port.c @@ -472,7 +472,7 @@ cleanup_old_port_data(erts_aint_t data) ErtsPortDataHeap *pdhp = (ErtsPortDataHeap *) data; size_t size; ERTS_SMP_DATA_DEPENDENCY_READ_MEMORY_BARRIER; - size = sizeof(ErtsPortDataHeap) + pdhp->hsize*(sizeof(Eterm) - 1); + size = sizeof(ErtsPortDataHeap) + (pdhp->hsize-1)*sizeof(Eterm); erts_schedule_thr_prgr_later_cleanup_op(free_port_data_heap, (void *) pdhp, &pdhp->later_op, @@ -508,7 +508,7 @@ erts_port_data_size(Port *prt) } else { ErtsPortDataHeap *pdhp = (ErtsPortDataHeap *) data; - return (Uint) sizeof(ErtsPortDataHeap) + pdhp->hsize*(sizeof(Eterm)-1); + return (Uint) sizeof(ErtsPortDataHeap) + (pdhp->hsize-1)*sizeof(Eterm); } } @@ -550,7 +550,7 @@ BIF_RETTYPE port_set_data_2(BIF_ALIST_2) hsize = size_object(BIF_ARG_2); pdhp = erts_alloc(ERTS_ALC_T_PORT_DATA_HEAP, - sizeof(ErtsPortDataHeap) + hsize*(sizeof(Eterm)-1)); + sizeof(ErtsPortDataHeap) + (hsize-1)*sizeof(Eterm)); hp = &pdhp->heap[0]; pdhp->off_heap.first = NULL; pdhp->off_heap.overhead = 0; diff --git a/erts/emulator/test/port_SUITE.erl b/erts/emulator/test/port_SUITE.erl index 78d76ccb64..8c904410b0 100644 --- a/erts/emulator/test/port_SUITE.erl +++ b/erts/emulator/test/port_SUITE.erl @@ -2297,8 +2297,10 @@ port_setget_data(Config) when is_list(Config) -> Port = erlang:open_port({spawn_driver, "echo_drv"}, []), NSched = erlang:system_info(schedulers_online), + HeapData = {1,2,3,<<"A heap binary">>,fun()->"This is fun"end, + list_to_binary(lists:seq(1,100))}, PRs = lists:map(fun(I) -> - spawn_opt(fun() -> port_setget_data_hammer(Port,1) end, + spawn_opt(fun() -> port_setget_data_hammer(Port,HeapData,false,1) end, [monitor, {scheduler, I rem NSched}]) end, lists:seq(1,10)), @@ -2316,13 +2318,17 @@ port_setget_data(Config) when is_list(Config) -> PRs), ok. -port_setget_data_hammer(Port, N) -> +port_setget_data_hammer(Port, HeapData, IsSet0, N) -> Rand = random:uniform(3), - try case Rand of - 1 -> true = erlang:port_set_data(Port, atom); - 2 -> true = erlang:port_set_data(Port, {1,2,3}); - 3 -> erlang:port_get_data(Port) - end + IsSet1 = try case Rand of + 1 -> true = erlang:port_set_data(Port, atom), true; + 2 -> true = erlang:port_set_data(Port, HeapData), true; + 3 -> case erlang:port_get_data(Port) of + atom -> true; + HeapData -> true; + undefined -> false=IsSet0 + end + end catch error:badarg -> true = get(prepare_for_close), @@ -2335,7 +2341,7 @@ port_setget_data_hammer(Port, N) -> after 0 -> ok end, - port_setget_data_hammer(Port, N+1). + port_setget_data_hammer(Port, HeapData, IsSet1, N+1). wait_until(Fun) -> -- cgit v1.2.3 From 82d5db1537fe1661051783ef909b103984e7661c Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Mon, 26 Jan 2015 10:30:45 +0100 Subject: Prepare release --- erts/doc/src/notes.xml | 19 +++++++++++++++++++ erts/vsn.mk | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/erts/doc/src/notes.xml b/erts/doc/src/notes.xml index dd9e7507df..442cebdc37 100644 --- a/erts/doc/src/notes.xml +++ b/erts/doc/src/notes.xml @@ -30,6 +30,25 @@

This document describes the changes made to the ERTS application.

+
Erts 5.10.4.3 + +
Fixed Bugs and Malfunctions + + +

+ Fix race bug that could cause VM crash in + erlang:port_get_data/1 if the port was closed by a + concurrent process. Also fix fatal bug if + port_set_data/2 is called with a non-immediate + data term. Both bugs exist since R16B01.

+

+ Own Id: OTP-12208

+
+
+
+ +
+
Erts 5.10.4.2
Improvements and New Features diff --git a/erts/vsn.mk b/erts/vsn.mk index 0b5ade5a7a..c8ab34f961 100644 --- a/erts/vsn.mk +++ b/erts/vsn.mk @@ -17,7 +17,7 @@ # %CopyrightEnd% # -VSN = 5.10.4.2 +VSN = 5.10.4.3 SYSTEM_VSN = R16B03-1 # Port number 4365 in 4.2 -- cgit v1.2.3