aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bootstrap/lib/compiler/ebin/beam_a.beambin2236 -> 2288 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_eval.beambin23220 -> 22692 bytes
-rw-r--r--erts/emulator/Makefile.in4
-rw-r--r--erts/emulator/test/port_SUITE.erl13
-rw-r--r--erts/preloaded/ebin/prim_eval.beambin0 -> 1352 bytes
-rw-r--r--erts/preloaded/src/.gitignore1
-rw-r--r--erts/preloaded/src/Makefile26
-rw-r--r--erts/preloaded/src/add_abstract_code34
-rw-r--r--erts/preloaded/src/prim_eval.S70
-rw-r--r--erts/preloaded/src/prim_eval.erl28
-rw-r--r--lib/compiler/src/beam_a.erl4
-rw-r--r--lib/compiler/src/beam_utils.erl4
-rw-r--r--lib/compiler/test/receive_SUITE.erl21
-rw-r--r--lib/diameter/doc/src/diameter_app.xml14
-rw-r--r--lib/diameter/doc/src/diameter_transport.xml7
-rw-r--r--lib/diameter/src/base/diameter_capx.erl19
-rw-r--r--lib/diameter/src/base/diameter_peer_fsm.erl50
-rw-r--r--lib/diameter/src/base/diameter_traffic.erl22
-rw-r--r--lib/diameter/test/diameter_3xxx_SUITE.erl36
-rw-r--r--lib/kernel/test/gen_tcp_misc_SUITE.erl2
-rw-r--r--lib/observer/src/observer_procinfo.erl56
-rw-r--r--lib/reltool/doc/src/reltool_examples.xml3
-rw-r--r--lib/sasl/src/systools_make.erl4
-rw-r--r--lib/stdlib/doc/src/erl_eval.xml5
-rw-r--r--lib/stdlib/src/erl_eval.erl64
-rw-r--r--lib/test_server/src/ts_install_cth.erl4
26 files changed, 377 insertions, 114 deletions
diff --git a/bootstrap/lib/compiler/ebin/beam_a.beam b/bootstrap/lib/compiler/ebin/beam_a.beam
index fd53a2e0f9..a4965abd48 100644
--- a/bootstrap/lib/compiler/ebin/beam_a.beam
+++ b/bootstrap/lib/compiler/ebin/beam_a.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_eval.beam b/bootstrap/lib/stdlib/ebin/erl_eval.beam
index 07f663b2c6..6f4180ee07 100644
--- a/bootstrap/lib/stdlib/ebin/erl_eval.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_eval.beam
Binary files differ
diff --git a/erts/emulator/Makefile.in b/erts/emulator/Makefile.in
index fb4cde0e76..58e83540e1 100644
--- a/erts/emulator/Makefile.in
+++ b/erts/emulator/Makefile.in
@@ -559,13 +559,14 @@ GENERATE += $(TTF_DIR)/driver_tab.c
# Preloaded code.
#
# This list must be consistent with PRE_LOADED_MODULES in
-# lib/kernel/src/Makefile.
+# erts/preloaded/src/Makefile.
ifeq ($(TARGET),win32)
# On windows the preloaded objects are in a resource object.
PRELOAD_OBJ = $(OBJDIR)/beams.$(RES_EXT)
PRELOAD_SRC = $(TARGET)/beams.rc
$(PRELOAD_SRC): $(ERL_TOP)/erts/preloaded/ebin/otp_ring0.beam \
$(ERL_TOP)/erts/preloaded/ebin/init.beam \
+ $(ERL_TOP)/erts/preloaded/ebin/prim_eval.beam \
$(ERL_TOP)/erts/preloaded/ebin/prim_inet.beam \
$(ERL_TOP)/erts/preloaded/ebin/prim_file.beam \
$(ERL_TOP)/erts/preloaded/ebin/zlib.beam \
@@ -579,6 +580,7 @@ PRELOAD_OBJ = $(OBJDIR)/preload.o
PRELOAD_SRC = $(TARGET)/preload.c
$(PRELOAD_SRC): $(ERL_TOP)/erts/preloaded/ebin/otp_ring0.beam \
$(ERL_TOP)/erts/preloaded/ebin/init.beam \
+ $(ERL_TOP)/erts/preloaded/ebin/prim_eval.beam \
$(ERL_TOP)/erts/preloaded/ebin/prim_inet.beam \
$(ERL_TOP)/erts/preloaded/ebin/prim_file.beam \
$(ERL_TOP)/erts/preloaded/ebin/zlib.beam \
diff --git a/erts/emulator/test/port_SUITE.erl b/erts/emulator/test/port_SUITE.erl
index 13aa0f4c00..e467e844b3 100644
--- a/erts/emulator/test/port_SUITE.erl
+++ b/erts/emulator/test/port_SUITE.erl
@@ -92,7 +92,7 @@
spawn_driver/1, spawn_executable/1, close_deaf_port/1,
unregister_name/1, parallelism_option/1]).
--export([]).
+-export([do_iter_max_ports/2]).
%% Internal exports.
-export([tps/3]).
@@ -635,9 +635,16 @@ iter_max_ports_test(Config) ->
{win32,_} -> 4;
_ -> 10
end,
- L = do_iter_max_ports(Iters, Command),
+ %% Run on a different node in order to limit the effect if this test fails.
+ Dir = filename:dirname(code:which(?MODULE)),
+ {ok,Node} = test_server:start_node(test_iter_max_socks,slave,
+ [{args,"+Q 2048 -pa " ++ Dir}]),
+ L = rpc:call(Node,?MODULE,do_iter_max_ports,[Iters, Command]),
+ test_server:stop_node(Node),
+
io:format("Result: ~p",[L]),
all_equal(L),
+ all_equal(L),
test_server:timetrap_cancel(Dog),
{comment, "Max ports: " ++ integer_to_list(hd(L))}.
@@ -670,7 +677,7 @@ close_ports([]) ->
ok.
open_ports(Name, Settings) ->
- test_server:sleep(50),
+ test_server:sleep(5),
case catch open_port(Name, Settings) of
P when is_port(P) ->
[P| open_ports(Name, Settings)];
diff --git a/erts/preloaded/ebin/prim_eval.beam b/erts/preloaded/ebin/prim_eval.beam
new file mode 100644
index 0000000000..6c7b7e5262
--- /dev/null
+++ b/erts/preloaded/ebin/prim_eval.beam
Binary files differ
diff --git a/erts/preloaded/src/.gitignore b/erts/preloaded/src/.gitignore
new file mode 100644
index 0000000000..e4658fe142
--- /dev/null
+++ b/erts/preloaded/src/.gitignore
@@ -0,0 +1 @@
+prim_eval.abstr
diff --git a/erts/preloaded/src/Makefile b/erts/preloaded/src/Makefile
index a224b6a5d4..f53809e765 100644
--- a/erts/preloaded/src/Makefile
+++ b/erts/preloaded/src/Makefile
@@ -32,7 +32,7 @@ STATIC_EBIN=../ebin
include $(ERL_TOP)/erts/vsn.mk
include $(ERL_TOP)/lib/kernel/vsn.mk
-PRE_LOADED_MODULES = \
+PRE_LOADED_ERL_MODULES = \
erl_prim_loader \
init \
prim_file \
@@ -43,10 +43,17 @@ PRE_LOADED_MODULES = \
erlang \
erts_internal
+PRE_LOADED_BEAM_MODULES = \
+ prim_eval
+
+PRE_LOADED_MODULES = $(PRE_LOADED_ERL_MODULES) $(PRE_LOADED_BEAM_MODULES)
+
RELSYSDIR = $(RELEASE_PATH)/lib/erts-$(VSN)
# not $(RELEASE_PATH)/erts-$(VSN)/preloaded
-ERL_FILES= $(PRE_LOADED_MODULES:%=%.erl)
+ERL_FILES= $(PRE_LOADED_ERL_MODULES:%=%.erl)
+BEAM_FILES= $(PRE_LOADED_BEAM_MODULES:%=%.S)
+STUBS_FILES= $(PRE_LOADED_BEAM_MODULES:%=%.erl)
TARGET_FILES = $(PRE_LOADED_MODULES:%=$(EBIN)/%.$(EMULATOR))
STATIC_TARGET_FILES = $(PRE_LOADED_MODULES:%=$(STATIC_EBIN)/%.$(EMULATOR))
@@ -70,7 +77,7 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec:
$(INSTALL_DIR) "$(RELSYSDIR)/src"
- $(INSTALL_DATA) $(ERL_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(ERL_FILES) $(BEAM_FILES) $(STUBS_FILES) "$(RELSYSDIR)/src"
$(INSTALL_DIR) "$(RELSYSDIR)/ebin"
$(INSTALL_DATA) $(STATIC_TARGET_FILES) "$(RELSYSDIR)/ebin"
@@ -80,6 +87,19 @@ release_docs_spec:
list_preloaded:
@echo $(PRE_LOADED_MODULES)
+#
+# Combine a BEAM assembly script file a stub Erlang file into a BEAM file.
+# See add_abstract_chunk script.
+#
+
+prim_eval.abstr: prim_eval.erl
+ $(V_ERLC) $(ERL_COMPILE_FLAGS) -o$(dir $@) +dabstr $<
+
+prim_eval.beam: prim_eval.S prim_eval.abstr
+ $(gen_verbose)
+ $(V_at)$(ERLC) $(ERL_COMPILE_FLAGS) $<
+ $(V_at)escript add_abstract_code $@ prim_eval.abstr || (rm $@; exit 1)
+
# Include dependencies -- list below added by PaN
$(EBIN)/erl_prim_loader.beam: $(KERNEL_SRC)/inet_boot.hrl $(KERNEL_INCLUDE)/file.hrl
$(EBIN)/prim_file.beam: $(KERNEL_INCLUDE)/file.hrl
diff --git a/erts/preloaded/src/add_abstract_code b/erts/preloaded/src/add_abstract_code
new file mode 100644
index 0000000000..e670156d21
--- /dev/null
+++ b/erts/preloaded/src/add_abstract_code
@@ -0,0 +1,34 @@
+#!/usr/bin/env escript
+%% -*- erlang -*-
+
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2013. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-mode(compile).
+
+-export([main/1]).
+
+main([BeamFile,AbstrFile]) ->
+ {ok,_,Chunks0} = beam_lib:all_chunks(BeamFile),
+ {ok,Abstr} = file:consult(AbstrFile),
+ Chunks = lists:keyreplace("Abst", 1, Chunks0,
+ {"Abst",term_to_binary({raw_abstract_v1,Abstr})}),
+ {ok,Module} = beam_lib:build_module(Chunks),
+ ok = file:write_file(BeamFile, Module),
+ init:stop().
diff --git a/erts/preloaded/src/prim_eval.S b/erts/preloaded/src/prim_eval.S
new file mode 100644
index 0000000000..958a79a1da
--- /dev/null
+++ b/erts/preloaded/src/prim_eval.S
@@ -0,0 +1,70 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2013. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+{module, prim_eval}.
+
+%% This module uses low-level BEAM instructions for the message queue facility
+%% to allow erl_eval to evaluate receive expressions correctly.
+
+{exports, [{'receive',2},{module_info,0},{module_info,1}]}.
+
+{attributes, []}.
+
+{labels, 10}.
+
+
+{function, 'receive', 2, 2}.
+ {label,1}.
+ {func_info,{atom,prim_eval},{atom,'receive'},2}.
+ {label,2}.
+ {allocate,2,2}.
+ {move,{x,1},{y,0}}.
+ {move,{x,0},{y,1}}.
+ {label,3}.
+ {loop_rec,{f,5},{x,0}}.
+ {move,{y,1},{x,1}}.
+ {call_fun,1}.
+ {test,is_ne_exact,{f,4},[{x,0},{atom,nomatch}]}.
+ remove_message.
+ {deallocate,2}.
+ return.
+ {label,4}.
+ {loop_rec_end,{f,3}}.
+ {label,5}.
+ {wait_timeout,{f,3},{y,0}}.
+ timeout.
+ {move,{atom,timeout},{x,0}}.
+ {deallocate,2}.
+ return.
+
+
+{function, module_info, 0, 8}.
+ {label,6}.
+ {func_info,{atom,prim_eval},{atom,module_info},0}.
+ {label,7}.
+ {move,{atom,prim_eval},{x,0}}.
+ {call_ext_only,1,{extfunc,erlang,get_module_info,1}}.
+
+
+{function, module_info, 1, 10}.
+ {label,8}.
+ {func_info,{atom,prim_eval},{atom,module_info},1}.
+ {label,9}.
+ {move,{x,0},{x,1}}.
+ {move,{atom,prim_eval},{x,0}}.
+ {call_ext_only,2,{extfunc,erlang,get_module_info,2}}.
diff --git a/erts/preloaded/src/prim_eval.erl b/erts/preloaded/src/prim_eval.erl
new file mode 100644
index 0000000000..ec5af8c138
--- /dev/null
+++ b/erts/preloaded/src/prim_eval.erl
@@ -0,0 +1,28 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2013. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(prim_eval).
+
+%% This module is simply a stub which abstract code gets included in the result
+%% of compilation of prim_eval.S, to keep Dialyzer happy.
+
+-export(['receive'/2]).
+
+-spec 'receive'(fun((term()) -> nomatch | T), timeout()) -> T.
+'receive'(_, _) ->
+ erlang:nif_error(stub).
diff --git a/lib/compiler/src/beam_a.erl b/lib/compiler/src/beam_a.erl
index 1c51226314..b348e854a0 100644
--- a/lib/compiler/src/beam_a.erl
+++ b/lib/compiler/src/beam_a.erl
@@ -70,8 +70,8 @@ rename_instr({bs_put_utf16=I,F,Fl,Src}) ->
{bs_put,F,{I,Fl},[Src]};
rename_instr({bs_put_utf32=I,F,Fl,Src}) ->
{bs_put,F,{I,Fl},[Src]};
-%% rename_instr({bs_put_string,_,_}=I) ->
-%% {bs_put,{f,0},I,[]};
+rename_instr({bs_put_string,_,_}=I) ->
+ {bs_put,{f,0},I,[]};
rename_instr({bs_add=I,F,[Src1,Src2,U],Dst}) when is_integer(U) ->
{bif,I,F,[Src1,Src2,{integer,U}],Dst};
rename_instr({bs_utf8_size=I,F,Src,Dst}) ->
diff --git a/lib/compiler/src/beam_utils.erl b/lib/compiler/src/beam_utils.erl
index 554c14f57a..e623bcc6a5 100644
--- a/lib/compiler/src/beam_utils.erl
+++ b/lib/compiler/src/beam_utils.erl
@@ -734,6 +734,8 @@ live_opt([{loop_rec,_Fail,_Dst}=I|Is], _, D, Acc) ->
live_opt(Is, 0, D, [I|Acc]);
live_opt([timeout=I|Is], _, D, Acc) ->
live_opt(Is, 0, D, [I|Acc]);
+live_opt([{wait,_}=I|Is], _, D, Acc) ->
+ live_opt(Is, 0, D, [I|Acc]);
%% Transparent instructions - they neither use nor modify x registers.
live_opt([{deallocate,_}=I|Is], Regs, D, Acc) ->
@@ -744,8 +746,6 @@ live_opt([{try_end,_}=I|Is], Regs, D, Acc) ->
live_opt(Is, Regs, D, [I|Acc]);
live_opt([{loop_rec_end,_}=I|Is], Regs, D, Acc) ->
live_opt(Is, Regs, D, [I|Acc]);
-live_opt([{wait,_}=I|Is], Regs, D, Acc) ->
- live_opt(Is, Regs, D, [I|Acc]);
live_opt([{wait_timeout,_,{Tag,_}}=I|Is], Regs, D, Acc) when Tag =/= x ->
live_opt(Is, Regs, D, [I|Acc]);
live_opt([{line,_}=I|Is], Regs, D, Acc) ->
diff --git a/lib/compiler/test/receive_SUITE.erl b/lib/compiler/test/receive_SUITE.erl
index e60584d4ab..ec49267ded 100644
--- a/lib/compiler/test/receive_SUITE.erl
+++ b/lib/compiler/test/receive_SUITE.erl
@@ -23,7 +23,8 @@
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,
init_per_testcase/2,end_per_testcase/2,
- export/1,recv/1,coverage/1,otp_7980/1,ref_opt/1]).
+ export/1,recv/1,coverage/1,otp_7980/1,ref_opt/1,
+ wait/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -44,7 +45,7 @@ all() ->
groups() ->
[{p,test_lib:parallel(),
- [recv,coverage,otp_7980,ref_opt,export]}].
+ [recv,coverage,otp_7980,ref_opt,export,wait]}].
init_per_suite(Config) ->
@@ -252,4 +253,20 @@ export_1(Reference) ->
id({build,self()}),
Result.
+wait(Config) when is_list(Config) ->
+ self() ! <<42>>,
+ <<42>> = wait_1(r, 1, 2),
+ {1,2,3} = wait_1(1, 2, 3),
+ ok.
+
+wait_1(r, _, _) ->
+ receive
+ B when byte_size(B) > 0 ->
+ B
+ end;
+%% beam_utils would wrongly assume that wait/1 could fall through
+%% to the next clause.
+wait_1(A, B, C) ->
+ {A,B,C}.
+
id(I) -> I.
diff --git a/lib/diameter/doc/src/diameter_app.xml b/lib/diameter/doc/src/diameter_app.xml
index d4fb792787..e6c9cc9a90 100644
--- a/lib/diameter/doc/src/diameter_app.xml
+++ b/lib/diameter/doc/src/diameter_app.xml
@@ -565,7 +565,8 @@ Equivalent to</p>
</pre>
<p>
where <c>Avps</c> sets the Origin-Host, Origin-Realm, the specified
-Result-Code and (if the request contained one) Session-Id AVP's.</p>
+Result-Code and (if the request contained one) Session-Id AVP's, and
+possibly Failed-AVP as described below.</p>
<p>
Returning a value other than 3xxx or 5xxx will cause the request
@@ -573,6 +574,14 @@ process in question to fail, as will returning a 5xxx value if the
peer connection in question has been configured with the RFC 3588
common dictionary <c>diameter_gen_base_rfc3588</c>.
(Since RFC 3588 only allows 3xxx values in an answer-message.)</p>
+
+<p>
+When returning 5xxx, Failed-AVP will be populated with the AVP of the
+first matching Result-Code/AVP pair in the <c>errors</c> field of the
+argument &packet;, if found.
+If this is not appropriate then an answer-message should be
+constructed explicitly and returned in a <c>reply</c> tuple
+instead.</p>
</item>
<tag><c>{relay, Opts}</c></tag>
@@ -592,8 +601,7 @@ header of the relayed request.</p>
The returned <c>Opts</c> should not specify <c>detach</c>.
A subsequent &handle_answer;
callback for the relayed request must return its first
-argument, the <c>#diameter_packet{}</c> record containing the answer
-message.
+argument, the &packet; containing the answer message.
Note that the <c>extra</c> option can be specified to supply arguments
that can distinguish the relay case from others if so desired.
Any other return value (for example, from a
diff --git a/lib/diameter/doc/src/diameter_transport.xml b/lib/diameter/doc/src/diameter_transport.xml
index 8bccf6521e..9161bd1f48 100644
--- a/lib/diameter/doc/src/diameter_transport.xml
+++ b/lib/diameter/doc/src/diameter_transport.xml
@@ -137,15 +137,14 @@ passed to the former.</p>
<p>
The start function should use the <c>Host-IP-Address</c> list in
-<c>Svc</c> and/or <c>Config</c> to select an appropriate list of local
-IP addresses, and should return this list if different from the
-<c>Svc</c> addresses.
+<c>Svc</c> and/or <c>Config</c> to select and return an appropriate
+list of local IP addresses.
In the connecting case, the local address list can instead be
communicated in a <c>connected</c> message (see &MESSAGES; below)
following connection establishment.
In either case, the local address list is used to populate
<c>Host-IP-Address</c> AVPs in outgoing capabilities exchange
-messages.</p>
+messages if <c>Host-IP-Address</c> is unspecified.</p>
<p>
A transport process must implement the message interface documented below.
diff --git a/lib/diameter/src/base/diameter_capx.erl b/lib/diameter/src/base/diameter_capx.erl
index 9a443fead0..4b821f5139 100644
--- a/lib/diameter/src/base/diameter_capx.erl
+++ b/lib/diameter/src/base/diameter_capx.erl
@@ -282,9 +282,26 @@ build_CEA(_, LCaps, RCaps, Dict, CEA) ->
[] ->
Dict:'#set-'({'Result-Code', ?NOSECURITY}, CEA);
[_] = IS ->
- Dict:'#set-'({'Inband-Security-Id', IS}, CEA)
+ Dict:'#set-'({'Inband-Security-Id', inband_security(IS)}, CEA)
end.
+%% Only set Inband-Security-Id if different from the default, since
+%% RFC 6733 recommends against the AVP:
+%%
+%% 6.10. Inband-Security-Id AVP
+%%
+%% The Inband-Security-Id AVP (AVP Code 299) is of type Unsigned32 and
+%% is used in order to advertise support of the security portion of the
+%% application. The use of this AVP in CER and CEA messages is NOT
+%% RECOMMENDED. Instead, discovery of a Diameter entity's security
+%% capabilities can be done either through static configuration or via
+%% Diameter Peer Discovery as described in Section 5.2.
+
+inband_security([?NO_INBAND_SECURITY]) ->
+ [];
+inband_security([_] = IS) ->
+ IS.
+
%% common_security/2
common_security(#diameter_caps{inband_security_id = LS},
diff --git a/lib/diameter/src/base/diameter_peer_fsm.erl b/lib/diameter/src/base/diameter_peer_fsm.erl
index 6be4259510..4e55864168 100644
--- a/lib/diameter/src/base/diameter_peer_fsm.erl
+++ b/lib/diameter/src/base/diameter_peer_fsm.erl
@@ -233,20 +233,21 @@ start_transport(Addrs0, T) ->
{TPid, Addrs, Tmo, Data} ->
erlang:monitor(process, TPid),
q_next(TPid, Addrs0, Tmo, Data),
- {TPid, addrs(Addrs, Addrs0)};
+ {TPid, Addrs};
No ->
exit({shutdown, No})
end.
-addrs([], Addrs0) ->
- Addrs0;
-addrs(Addrs, _) ->
- Addrs.
-
-svc(Svc, []) ->
- Svc;
-svc(Svc, Addrs) ->
- readdr(Svc, Addrs).
+svc(#diameter_service{capabilities = LCaps0} = Svc, Addrs) ->
+ #diameter_caps{host_ip_address = Addrs0}
+ = LCaps0,
+ case Addrs0 of
+ [] ->
+ LCaps = LCaps0#diameter_caps{host_ip_address = Addrs},
+ Svc#diameter_service{capabilities = LCaps};
+ [_|_] ->
+ Svc
+ end.
readdr(#diameter_service{capabilities = LCaps0} = Svc, Addrs) ->
LCaps = LCaps0#diameter_caps{host_ip_address = Addrs},
@@ -360,7 +361,7 @@ transition({diameter, {TPid, connected, Remote, LAddrs}},
service = Svc}
= S) ->
transition({diameter, {TPid, connected, Remote}},
- S#state{service = readdr(Svc, LAddrs)});
+ S#state{service = svc(Svc, LAddrs)});
%% Connection from peer.
transition({diameter, {TPid, connected}},
@@ -702,13 +703,13 @@ build_answer('CER',
N -> {cea(CEA, N, Dict0), [fun open/5, Pkt,
SupportedApps,
Caps,
- {accept, hd([_] = IS)}]}
+ {accept, inband_security(IS)}]}
catch
?FAILURE(Reason) ->
rejected(Reason, {'CER', Reason, Caps, Pkt}, S)
end;
-%% The error checks below are similar to those in diameter_service for
+%% The error checks below are similar to those in diameter_traffic for
%% other messages. Should factor out the commonality.
build_answer(Type,
@@ -719,6 +720,11 @@ build_answer(Type,
RC = rc(H, Es),
{answer(Type, RC, Es, S), post(Type, RC, Pkt, S)}.
+inband_security([]) ->
+ ?NO_INBAND_SECURITY;
+inband_security([IS]) ->
+ IS.
+
cea(CEA, ok, _) ->
CEA;
cea(CEA, 2001, _) ->
@@ -742,7 +748,14 @@ rejected(N, T, S) ->
rejected({N, []}, T, S).
answer(Type, RC, Es, S) ->
- set(answer(Type, RC, S), failed_avp([A || {_,A} <- Es])).
+ set(answer(Type, RC, S), failed_avp(RC, Es)).
+
+failed_avp(RC, [{RC, Avp} | _]) ->
+ [{'Failed-AVP', [{'AVP', [Avp]}]}];
+failed_avp(RC, [_ | Es]) ->
+ failed_avp(RC, Es);
+failed_avp(_, [] = No) ->
+ No.
answer(Type, RC, S) ->
answer_message(answer(Type, S), RC).
@@ -762,13 +775,6 @@ is_origin({N, _}) ->
orelse N == 'Origin-Realm'
orelse N == 'Origin-State-Id'.
-%% failed_avp/1
-
-failed_avp([] = No) ->
- No;
-failed_avp(Avps) ->
- [{'Failed-AVP', [[{'AVP', Avps}]]}].
-
%% set/2
set(Ans, []) ->
@@ -784,7 +790,7 @@ rc(#diameter_header{is_error = true}, _) ->
3008; %% DIAMETER_INVALID_HDR_BITS
rc(_, [Bs|_])
- when is_bitstring(Bs) ->
+ when is_bitstring(Bs) -> %% from old code
3009; %% DIAMETER_INVALID_HDR_BITS
rc(#diameter_header{version = ?DIAMETER_VERSION}, Es) ->
diff --git a/lib/diameter/src/base/diameter_traffic.erl b/lib/diameter/src/base/diameter_traffic.erl
index 820d37535a..0b15e68ec7 100644
--- a/lib/diameter/src/base/diameter_traffic.erl
+++ b/lib/diameter/src/base/diameter_traffic.erl
@@ -479,10 +479,9 @@ answer_message(RC,
#diameter_caps{origin_host = {OH,_},
origin_realm = {OR,_}},
Dict0,
- #diameter_packet{avps = Avps}
- = Pkt) ->
+ Pkt) ->
?LOG({error, RC}, Pkt),
- {Dict0, answer_message(OH, OR, RC, Dict0, Avps)}.
+ {Dict0, answer_message(OH, OR, RC, Dict0, Pkt)}.
%% resend/7
@@ -861,12 +860,14 @@ failed(Rec, FailedAvp, Dict) ->
%% answer_message/5
-answer_message(OH, OR, RC, Dict0, Avps) ->
+answer_message(OH, OR, RC, Dict0, #diameter_packet{avps = Avps,
+ errors = Es}) ->
{Code, _, Vid} = Dict0:avp_header('Session-Id'),
['answer-message', {'Origin-Host', OH},
{'Origin-Realm', OR},
- {'Result-Code', RC}
- | session_id(Code, Vid, Dict0, Avps)].
+ {'Result-Code', RC}]
+ ++ session_id(Code, Vid, Dict0, Avps)
+ ++ failed_avp(RC, Es).
session_id(Code, Vid, Dict0, Avps)
when is_list(Avps) ->
@@ -878,6 +879,15 @@ session_id(Code, Vid, Dict0, Avps)
[]
end.
+%% Note that this should only match 5xxx result codes currently but
+%% don't bother distinguishing this case.
+failed_avp(RC, [{RC, Avp} | _]) ->
+ [{'Failed-AVP', [{'AVP', [Avp]}]}];
+failed_avp(RC, [_ | Es]) ->
+ failed_avp(RC, Es);
+failed_avp(_, [] = No) ->
+ No.
+
%% find_avp/3
find_avp(Code, Vid, Avps)
diff --git a/lib/diameter/test/diameter_3xxx_SUITE.erl b/lib/diameter/test/diameter_3xxx_SUITE.erl
index 0ec0d5020f..071b1a1177 100644
--- a/lib/diameter/test/diameter_3xxx_SUITE.erl
+++ b/lib/diameter/test/diameter_3xxx_SUITE.erl
@@ -43,6 +43,7 @@
send_invalid_hdr_bits/1,
send_missing_avp/1,
send_ignore_missing_avp/1,
+ send_5xxx_missing_avp/1,
send_double_error/1,
send_3xxx/1,
send_5xxx/1,
@@ -139,6 +140,7 @@ tc() ->
send_invalid_hdr_bits,
send_missing_avp,
send_ignore_missing_avp,
+ send_5xxx_missing_avp,
send_double_error,
send_3xxx,
send_5xxx].
@@ -279,6 +281,32 @@ send_ignore_missing_avp([_,_]) ->
send_ignore_missing_avp(Config) ->
send_ignore_missing_avp(?group(Config)).
+%% send_5xxx_missing_avp/1
+%%
+%% Send a request with a missing AVP that a callback answers
+%% with {answer_message, 5005}.
+
+%% RFC 6733 allows 5xxx in an answer-message.
+send_5xxx_missing_avp([_, rfc6733]) ->
+ #'diameter_base_answer-message'{'Result-Code' = 5005, %% MISSING_AVP
+ 'Failed-AVP' = [_],
+ 'AVP' = []}
+ = call();
+
+%% RFC 3588 doesn't: sending answer fails.
+send_5xxx_missing_avp([_, rfc3588]) ->
+ {error, timeout} = call();
+
+%% Callback answers, ignores the error
+send_5xxx_missing_avp([_,_]) ->
+ #diameter_base_STA{'Result-Code' = 2001, %% SUCCESS
+ 'Failed-AVP' = [],
+ 'AVP' = []}
+ = call();
+
+send_5xxx_missing_avp(Config) ->
+ send_5xxx_missing_avp(?group(Config)).
+
%% send_double_error/1
%%
%% Send a request with both an invalid E-bit and a missing AVP.
@@ -403,7 +431,8 @@ prepare(Pkt0, Caps, send_double_error) ->
prepare(Pkt, Caps, T)
when T == send_missing_avp;
- T == send_ignore_missing_avp ->
+ T == send_ignore_missing_avp;
+ T == send_5xxx_missing_avp ->
Req = sta(Pkt, Caps),
dehost(diameter_codec:encode(?DICT, Pkt#diameter_packet{msg = Req})).
@@ -487,7 +516,10 @@ request(T, Req, Caps)
request(send_ignore_missing_avp, Req, Caps) ->
{reply, #diameter_packet{msg = answer(Req, Caps),
- errors = false}}. %% ignore errors
+ errors = false}}; %% ignore errors
+
+request(send_5xxx_missing_avp, _Req, _Caps) ->
+ {answer_message, 5005}. %% MISSING_AVP
answer(Req, Caps) ->
#diameter_base_STR{'Session-Id' = SId}
diff --git a/lib/kernel/test/gen_tcp_misc_SUITE.erl b/lib/kernel/test/gen_tcp_misc_SUITE.erl
index 6b672004ec..2d5827282f 100644
--- a/lib/kernel/test/gen_tcp_misc_SUITE.erl
+++ b/lib/kernel/test/gen_tcp_misc_SUITE.erl
@@ -602,7 +602,7 @@ iter_max_socks(Config) when is_list(Config) ->
%% Run on a different node in order to limit the effect if this test fails.
Dir = filename:dirname(code:which(?MODULE)),
{ok,Node} = test_server:start_node(test_iter_max_socks,slave,
- [{args,"-pa " ++ Dir}]),
+ [{args,"+Q 2048 -pa " ++ Dir}]),
L = rpc:call(Node,?MODULE,do_iter_max_socks,[N, initalize]),
test_server:stop_node(Node),
diff --git a/lib/observer/src/observer_procinfo.erl b/lib/observer/src/observer_procinfo.erl
index 45218c177b..f234218017 100644
--- a/lib/observer/src/observer_procinfo.erl
+++ b/lib/observer/src/observer_procinfo.erl
@@ -64,6 +64,7 @@ init([Pid, ParentFrame, Parent]) ->
MessagePage = init_panel(Notebook, "Messages", Pid, fun init_message_page/2),
DictPage = init_panel(Notebook, "Dictionary", Pid, fun init_dict_page/2),
StackPage = init_panel(Notebook, "Stack Trace", Pid, fun init_stack_page/2),
+ StatePage = init_panel(Notebook, "State", Pid, fun init_state_page/2),
wxFrame:connect(Frame, close_window),
wxMenu:connect(Frame, command_menu_selected),
@@ -72,7 +73,7 @@ init([Pid, ParentFrame, Parent]) ->
{Frame, #state{parent=Parent,
pid=Pid,
frame=Frame,
- pages=[ProcessPage,MessagePage,DictPage,StackPage]
+ pages=[ProcessPage,MessagePage,DictPage,StackPage,StatePage]
}}
catch error:{badrpc, _} ->
observer_wx:return_to_localnode(ParentFrame, node(Pid)),
@@ -235,6 +236,59 @@ init_stack_page(Parent, Pid) ->
Update(),
{LCtrl, Update}.
+
+init_state_page(Parent, Pid) ->
+ Text = init_text_page(Parent),
+ Update = fun() ->
+ %% First, test if sys:get_status/2 have any chance to return an answer
+ case rpc:call(node(Pid), proc_lib, translate_initial_call, [Pid])
+ of
+ %% Not a gen process
+ {proc_lib,init_p,5} -> Misc = [{"Information", "Not available"}];
+ %% May be a gen process
+ {M, _F, _A} ->
+ %% Get the behavio(u)r
+ I = rpc:call(node(Pid), M, module_info, [attributes]),
+ case lists:keyfind(behaviour, 1, I) of
+ false -> case lists:keyfind(behavior, 1, I) of
+ false -> B = undefined;
+ {behavior, [B]} -> B
+ end;
+ {behaviour, [B]} -> B
+ end,
+ %% but not sure that system messages are treated by this process
+ %% so using a rpc with a small timeout in order not to lag the display
+ case rpc:call(node(Pid), sys, get_status, [Pid, 200])
+ of
+ {status, _, {module, _}, [_PDict, _SysState, _Parent, _Dbg,
+ [Header,{data, First},{data, Second}]]} ->
+ Misc = [{"Behaviour", B}] ++ [Header] ++ First ++ Second;
+ {status, _, {module, _}, [_PDict, _SysState, _Parent, _Dbg,
+ [Header,{data, First}, OtherFormat]]} ->
+ Misc = [{"Behaviour", B}] ++ [Header] ++ First ++ [{"State",OtherFormat}];
+ {status, _, {module, _}, [_PDict, _SysState, _Parent, _Dbg,
+ OtherFormat]} ->
+ %% Formatted status ?
+ case lists:keyfind(format_status, 1, rpc:call(node(Pid), M, module_info, [exports])) of
+ false -> Opt = {"Format", unknown};
+ _ -> Opt = {"Format", overriden}
+ end,
+ Misc = [{"Behaviour", B}] ++ [Opt, {"State",OtherFormat}];
+ {badrpc,{'EXIT',{timeout, _}}} ->
+ Misc = [{"Information","Timed out"},
+ {"Tip","system messages are probably not treated by this process"}]
+ end;
+ _ -> Misc=[], throw(process_undefined)
+ end,
+ Dict = [io_lib:format("~-20.s ~tp~n", [K, V]) || {K, V} <- Misc],
+ Last = wxTextCtrl:getLastPosition(Text),
+ wxTextCtrl:remove(Text, 0, Last),
+ wxTextCtrl:writeText(Text, Dict)
+ end,
+ Update(),
+ {Text, Update}.
+
+
create_menus(MenuBar) ->
Menus = [{"File", [#create_menu{id=?wxID_CLOSE, text="Close"}]},
{"View", [#create_menu{id=?REFRESH, text="Refresh\tCtrl-R"}]}],
diff --git a/lib/reltool/doc/src/reltool_examples.xml b/lib/reltool/doc/src/reltool_examples.xml
index 19a3f37819..de243343ff 100644
--- a/lib/reltool/doc/src/reltool_examples.xml
+++ b/lib/reltool/doc/src/reltool_examples.xml
@@ -261,7 +261,8 @@ Eshell V5.7.3 (abort with ^G)
8&gt; reltool:get_script(Server, "NAME").
{ok,{script,{"NAME","VSN"},
[{preLoaded,[erl_prim_loader,erlang,init,otp_ring0,
- prim_file,prim_inet,prim_zip,zlib]},
+ prim_eval,prim_file,prim_inet,prim_zip,
+ zlib]},
{progress,preloaded},
{path,["$ROOT/lib/kernel-2.13/ebin",
"$ROOT/lib/stdlib-1.16/ebin"]},
diff --git a/lib/sasl/src/systools_make.erl b/lib/sasl/src/systools_make.erl
index 193dbb64bf..b2e95fdbee 100644
--- a/lib/sasl/src/systools_make.erl
+++ b/lib/sasl/src/systools_make.erl
@@ -1461,8 +1461,8 @@ mandatory_modules() ->
preloaded() ->
%% Sorted
- [erl_prim_loader,erlang,erts_internal,init,otp_ring0,prim_file,prim_inet,
- prim_zip,zlib].
+ [erl_prim_loader,erlang,erts_internal,init,otp_ring0,prim_eval,prim_file,
+ prim_inet,prim_zip,zlib].
%%______________________________________________________________________
%% Kernel processes; processes that are specially treated by the init
diff --git a/lib/stdlib/doc/src/erl_eval.xml b/lib/stdlib/doc/src/erl_eval.xml
index d0622594d9..24940f8396 100644
--- a/lib/stdlib/doc/src/erl_eval.xml
+++ b/lib/stdlib/doc/src/erl_eval.xml
@@ -288,10 +288,7 @@ Func(FuncSpec, Arguments) </code>
<section>
<title>Bugs</title>
- <p>The evaluator is not complete. <c>receive</c> cannot be
- handled properly.
- </p>
- <p>Any undocumented functions in <c>erl_eval</c> should not be used.</p>
+ <p>Undocumented functions in <c>erl_eval</c> should not be used.</p>
</section>
</erlref>
diff --git a/lib/stdlib/src/erl_eval.erl b/lib/stdlib/src/erl_eval.erl
index 0b57af1b6d..73b8da335a 100644
--- a/lib/stdlib/src/erl_eval.erl
+++ b/lib/stdlib/src/erl_eval.erl
@@ -245,10 +245,10 @@ expr({'case',_,E,Cs}, Bs0, Lf, Ef, RBs) ->
expr({'try',_,B,Cases,Catches,AB}, Bs, Lf, Ef, RBs) ->
try_clauses(B, Cases, Catches, AB, Bs, Lf, Ef, RBs);
expr({'receive',_,Cs}, Bs, Lf, Ef, RBs) ->
- receive_clauses(Cs, Bs, Lf, Ef, [], RBs);
+ receive_clauses(Cs, Bs, Lf, Ef, RBs);
expr({'receive',_, Cs, E, TB}, Bs0, Lf, Ef, RBs) ->
{value,T,Bs} = expr(E, Bs0, Lf, Ef, none),
- receive_clauses(T, Cs, {TB,Bs}, Bs0, Lf, Ef, [], RBs);
+ receive_clauses(T, Cs, {TB,Bs}, Bs0, Lf, Ef, RBs);
expr({'fun',_Line,{function,Mod0,Name0,Arity0}}, Bs0, Lf, Ef, RBs) ->
{[Mod,Name,Arity],Bs} = expr_list([Mod0,Name0,Arity0], Bs0, Lf, Ef),
F = erlang:make_fun(Mod, Name, Arity),
@@ -807,66 +807,24 @@ case_clauses(Val, Cs, Bs, Lf, Ef, RBs) ->
end.
%%
-%% receive_clauses(Clauses, Bindings, LocalFuncHnd,ExtFuncHnd, Messages, RBs)
+%% receive_clauses(Clauses, Bindings, LocalFuncHnd,ExtFuncHnd, RBs)
%%
-receive_clauses(Cs, Bs, Lf, Ef, Ms, RBs) ->
- receive
- Val ->
- case match_clause(Cs, [Val], Bs, Lf, Ef) of
- {B, Bs1} ->
- merge_queue(Ms),
- exprs(B, Bs1, Lf, Ef, RBs);
- nomatch ->
- receive_clauses(Cs, Bs, Lf, Ef, [Val|Ms], RBs)
- end
- end.
+receive_clauses(Cs, Bs, Lf, Ef, RBs) ->
+ receive_clauses(infinity, Cs, unused, Bs, Lf, Ef, RBs).
%%
%% receive_clauses(TimeOut, Clauses, TimeoutBody, Bindings,
%% ExternalFuncHandler, LocalFuncHandler, RBs)
%%
-receive_clauses(T, Cs, TB, Bs, Lf, Ef, Ms, RBs) ->
- {_,_} = statistics(runtime),
- receive
- Val ->
- case match_clause(Cs, [Val], Bs, Lf, Ef) of
- {B, Bs1} ->
- merge_queue(Ms),
- exprs(B, Bs1, Lf, Ef, RBs);
- nomatch ->
- {_,T1} = statistics(runtime),
- if
- T =:= infinity ->
- receive_clauses(T, Cs, TB,Bs,Lf,Ef,[Val|Ms],RBs);
- T-T1 =< 0 ->
- receive_clauses(0, Cs, TB,Bs,Lf,Ef,[Val|Ms],RBs);
- true ->
- receive_clauses(T-T1, Cs,TB,Bs,Lf,Ef,[Val|Ms],RBs)
- end
- end
- after T ->
- merge_queue(Ms),
+receive_clauses(T, Cs, TB, Bs, Lf, Ef, RBs) ->
+ F = fun (M) -> match_clause(Cs, [M], Bs, Lf, Ef) end,
+ case prim_eval:'receive'(F, T) of
+ {B, Bs1} ->
+ exprs(B, Bs1, Lf, Ef, RBs);
+ timeout ->
{B, Bs1} = TB,
exprs(B, Bs1, Lf, Ef, RBs)
end.
-merge_queue([]) ->
- true;
-merge_queue(Ms) ->
- send_all(recv_all(Ms), self()).
-
-recv_all(Xs) ->
- receive
- X -> recv_all([X|Xs])
- after 0 ->
- reverse(Xs)
- end.
-
-send_all([X|Xs], Self) ->
- Self ! X,
- send_all(Xs, Self);
-send_all([], _) -> true.
-
-
%% match_clause -> {Body, Bindings} or nomatch
-spec(match_clause(Clauses, ValueList, Bindings, LocalFunctionHandler) ->
diff --git a/lib/test_server/src/ts_install_cth.erl b/lib/test_server/src/ts_install_cth.erl
index 9b6e10e7e2..a75cae3c9d 100644
--- a/lib/test_server/src/ts_install_cth.erl
+++ b/lib/test_server/src/ts_install_cth.erl
@@ -103,7 +103,9 @@ pre_init_per_suite(_Suite,Config,State) ->
end,
{add_node_name(Config, State), State}
- catch Error:Reason ->
+ catch error:{badmatch,{error,enoent}} ->
+ {add_node_name(Config, State), State};
+ Error:Reason ->
Stack = erlang:get_stacktrace(),
ct:pal("~p failed! ~p:{~p,~p}",[?MODULE,Error,Reason,Stack]),
{{fail,{?MODULE,{Error,Reason, Stack}}},State}