From e8d0a8654ecf85f89a0c0f7aa26da8bc467e9373 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Fri, 2 Mar 2018 16:51:11 +0100 Subject: stdlib: Remove obsolete use of monitor_node as fallback when erlang:monitor failed toward primitive nodes, which it does not do in OTP-21. --- lib/stdlib/src/gen.erl | 38 ++------------------------------------ 1 file changed, 2 insertions(+), 36 deletions(-) (limited to 'lib/stdlib/src') diff --git a/lib/stdlib/src/gen.erl b/lib/stdlib/src/gen.erl index 0e6f49d99f..dc957b4d4e 100644 --- a/lib/stdlib/src/gen.erl +++ b/lib/stdlib/src/gen.erl @@ -158,8 +158,7 @@ call(Process, Label, Request, Timeout) do_for_proc(Process, Fun). do_call(Process, Label, Request, Timeout) -> - try erlang:monitor(process, Process) of - Mref -> + Mref = erlang:monitor(process, Process), %% If the monitor/2 call failed to set up a connection to a %% remote node, we don't want the '!' operator to attempt %% to set up the connection again. (If the monitor/2 call @@ -183,27 +182,7 @@ do_call(Process, Label, Request, Timeout) -> after Timeout -> erlang:demonitor(Mref, [flush]), exit(timeout) - end - catch - error:_ -> - %% Node (C/Java?) is not supporting the monitor. - %% The other possible case -- this node is not distributed - %% -- should have been handled earlier. - %% Do the best possible with monitor_node/2. - %% This code may hang indefinitely if the Process - %% does not exist. It is only used for featureweak remote nodes. - Node = get_node(Process), - monitor_node(Node, true), - receive - {nodedown, Node} -> - monitor_node(Node, false), - exit({nodedown, Node}) - after 0 -> - Tag = make_ref(), - Process ! {Label, {self(), Tag}, Request}, - wait_resp(Node, Tag, Timeout) - end - end. + end. get_node(Process) -> %% We trust the arguments to be correct, i.e @@ -217,19 +196,6 @@ get_node(Process) -> node(Process) end. -wait_resp(Node, Tag, Timeout) -> - receive - {Tag, Reply} -> - monitor_node(Node, false), - {ok, Reply}; - {nodedown, Node} -> - monitor_node(Node, false), - exit({nodedown, Node}) - after Timeout -> - monitor_node(Node, false), - exit(timeout) - end. - %% %% Send a reply to the client. %% -- cgit v1.2.3 From 3e580e039a8eb2467c638503bc526116fe829fec Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Fri, 2 Mar 2018 16:56:13 +0100 Subject: kernel,stdlib: Remove obsolete use of send with 'noconnect' as workarounds to avoid blocking auto-connect, which is now asynchronous in OTP-21. Also changed old catch to more efficient try-catch. --- lib/stdlib/src/gen.erl | 45 ++++++++++++++++++++----------------------- lib/stdlib/src/gen_server.erl | 11 +++++------ lib/stdlib/src/gen_statem.erl | 13 ++++--------- 3 files changed, 30 insertions(+), 39 deletions(-) (limited to 'lib/stdlib/src') diff --git a/lib/stdlib/src/gen.erl b/lib/stdlib/src/gen.erl index dc957b4d4e..293cb98ad2 100644 --- a/lib/stdlib/src/gen.erl +++ b/lib/stdlib/src/gen.erl @@ -159,30 +159,27 @@ call(Process, Label, Request, Timeout) do_call(Process, Label, Request, Timeout) -> Mref = erlang:monitor(process, Process), - %% If the monitor/2 call failed to set up a connection to a - %% remote node, we don't want the '!' operator to attempt - %% to set up the connection again. (If the monitor/2 call - %% failed due to an expired timeout, '!' too would probably - %% have to wait for the timeout to expire.) Therefore, - %% use erlang:send/3 with the 'noconnect' option so that it - %% will fail immediately if there is no connection to the - %% remote node. - - catch erlang:send(Process, {Label, {self(), Mref}, Request}, - [noconnect]), - receive - {Mref, Reply} -> - erlang:demonitor(Mref, [flush]), - {ok, Reply}; - {'DOWN', Mref, _, _, noconnection} -> - Node = get_node(Process), - exit({nodedown, Node}); - {'DOWN', Mref, _, _, Reason} -> - exit(Reason) - after Timeout -> - erlang:demonitor(Mref, [flush]), - exit(timeout) - end. + %% OTP-21: + %% Auto-connect is asynchronous. But we still use 'noconnect' to make sure + %% we send on the monitored connection, and not trigger a new auto-connect. + try erlang:send(Process, {Label, {self(), Mref}, Request}, [noconnect]) + catch + error:_ -> ok + end, + + receive + {Mref, Reply} -> + erlang:demonitor(Mref, [flush]), + {ok, Reply}; + {'DOWN', Mref, _, _, noconnection} -> + Node = get_node(Process), + exit({nodedown, Node}); + {'DOWN', Mref, _, _, Reason} -> + exit(Reason) + after Timeout -> + erlang:demonitor(Mref, [flush]), + exit(timeout) + end. get_node(Process) -> %% We trust the arguments to be correct, i.e diff --git a/lib/stdlib/src/gen_server.erl b/lib/stdlib/src/gen_server.erl index 77a46419f6..f29314d0a2 100644 --- a/lib/stdlib/src/gen_server.erl +++ b/lib/stdlib/src/gen_server.erl @@ -437,12 +437,11 @@ decode_msg(Msg, Parent, Name, State, Mod, Time, HibernateAfterTimeout, Debug, Hi %%% Send/receive functions %%% --------------------------------------------------- do_send(Dest, Msg) -> - case catch erlang:send(Dest, Msg, [noconnect]) of - noconnect -> - spawn(erlang, send, [Dest,Msg]); - Other -> - Other - end. + try erlang:send(Dest, Msg) + catch + error:_ -> ok + end, + ok. do_multi_call(Nodes, Name, Req, infinity) -> Tag = make_ref(), diff --git a/lib/stdlib/src/gen_statem.erl b/lib/stdlib/src/gen_statem.erl index f95b2ea9cd..9dc360a289 100644 --- a/lib/stdlib/src/gen_statem.erl +++ b/lib/stdlib/src/gen_statem.erl @@ -641,16 +641,11 @@ replies([]) -> %% Might actually not send the message in case of caught exception send(Proc, Msg) -> - try erlang:send(Proc, Msg, [noconnect]) of - noconnect -> - _ = spawn(erlang, send, [Proc,Msg]), - ok; - ok -> - ok + try erlang:send(Proc, Msg) catch - _:_ -> - ok - end. + error:_ -> ok + end, + ok. %% Here the init_it/6 and enter_loop/5,6,7 functions converge enter(Module, Opts, State, Data, Server, Actions, Parent) -> -- cgit v1.2.3 From 5a1b9a836675b025eb1611f23ee9e2f5e4efa156 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Mon, 5 Mar 2018 15:47:59 +0100 Subject: stdlib: Fix receive-ref optimization for gen_server:call Optimization does not trigger for try-catch. But send cannot fail here anyway, as Process cannot be an atom. --- lib/stdlib/src/gen.erl | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'lib/stdlib/src') diff --git a/lib/stdlib/src/gen.erl b/lib/stdlib/src/gen.erl index 293cb98ad2..2e6223d2bb 100644 --- a/lib/stdlib/src/gen.erl +++ b/lib/stdlib/src/gen.erl @@ -157,15 +157,14 @@ call(Process, Label, Request, Timeout) Fun = fun(Pid) -> do_call(Pid, Label, Request, Timeout) end, do_for_proc(Process, Fun). -do_call(Process, Label, Request, Timeout) -> +do_call(Process, Label, Request, Timeout) when is_atom(Process) =:= false -> Mref = erlang:monitor(process, Process), + %% OTP-21: %% Auto-connect is asynchronous. But we still use 'noconnect' to make sure %% we send on the monitored connection, and not trigger a new auto-connect. - try erlang:send(Process, {Label, {self(), Mref}, Request}, [noconnect]) - catch - error:_ -> ok - end, + %% + erlang:send(Process, {Label, {self(), Mref}, Request}, [noconnect]), receive {Mref, Reply} -> -- cgit v1.2.3