aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/compiler/test/receive_SUITE_data/ref_opt/yes_5.erl6
-rw-r--r--lib/debugger/src/dbg_debugged.erl14
-rw-r--r--lib/et/src/et_collector.erl9
-rw-r--r--lib/kernel/src/application_master.erl9
-rw-r--r--lib/kernel/src/disk_log.erl18
-rw-r--r--lib/kernel/src/file.erl43
-rw-r--r--lib/kernel/src/file_io_server.erl3
-rw-r--r--lib/kernel/src/file_server.erl3
-rw-r--r--lib/kernel/src/inet_gethost_native.erl3
-rw-r--r--lib/kernel/src/rpc.erl24
-rw-r--r--lib/kernel/test/file_SUITE.erl29
-rw-r--r--lib/kernel/test/gen_sctp_SUITE.erl3
-rw-r--r--lib/orber/src/orber_iiop_outproxy.erl35
-rw-r--r--lib/runtime_tools/src/dbg.erl6
-rw-r--r--lib/snmp/src/agent/snmpa_target_cache.erl37
-rw-r--r--lib/stdlib/src/dets.erl9
-rw-r--r--lib/stdlib/src/epp.erl3
-rw-r--r--lib/stdlib/src/gen_server.erl18
-rw-r--r--lib/stdlib/src/io.erl6
-rw-r--r--lib/stdlib/src/supervisor.erl27
-rw-r--r--lib/stdlib/test/Makefile1
-rw-r--r--lib/stdlib/test/supervisor_3.erl45
-rw-r--r--lib/stdlib/test/supervisor_SUITE.erl106
-rw-r--r--lib/tools/src/fprof.erl8
24 files changed, 261 insertions, 204 deletions
diff --git a/lib/compiler/test/receive_SUITE_data/ref_opt/yes_5.erl b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_5.erl
index 3f02fba6a6..5070e3e546 100644
--- a/lib/compiler/test/receive_SUITE_data/ref_opt/yes_5.erl
+++ b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_5.erl
@@ -24,11 +24,7 @@ do_call(Process, Label, Request, Timeout) ->
{'DOWN', Mref, _, _, Reason} ->
exit(Reason)
after Timeout ->
- erlang:demonitor(Mref),
- receive
- {'DOWN', Mref, _, _, _} -> true
- after 0 -> true
- end,
+ erlang:demonitor(Mref, [flush]),
exit(timeout)
end
catch
diff --git a/lib/debugger/src/dbg_debugged.erl b/lib/debugger/src/dbg_debugged.erl
index c21ad486e8..d8285d7288 100644
--- a/lib/debugger/src/dbg_debugged.erl
+++ b/lib/debugger/src/dbg_debugged.erl
@@ -19,8 +19,6 @@
-module(dbg_debugged).
%% External exports
-%% Avoid warning for local function demonitor/1 clashing with autoimported BIF.
--compile({no_auto_import,[demonitor/1]}).
-export([eval/3]).
%%====================================================================
@@ -47,7 +45,7 @@ msg_loop(Meta, Mref, SaveStacktrace) ->
%% Evaluated function has returned a value
{sys, Meta, {ready, Val}} ->
- demonitor(Mref),
+ erlang:demonitor(Mref, [flush]),
%% Restore original stacktrace and return the value
try erlang:raise(throw, stack, SaveStacktrace)
@@ -63,7 +61,7 @@ msg_loop(Meta, Mref, SaveStacktrace) ->
%% Evaluated function raised an (uncaught) exception
{sys, Meta, {exception,{Class,Reason,Stacktrace}}} ->
- demonitor(Mref),
+ erlang:demonitor(Mref, [flush]),
%% ...raise the same exception
erlang:error(erlang:raise(Class, Reason, Stacktrace),
@@ -107,14 +105,6 @@ reply({eval,Expr,Bs}) ->
%% Bindings is an orddict (sort them)
erl_eval:expr(Expr, lists:sort(Bs)). % {value, Value, Bs2}
-%% Demonitor and delete message from inbox
-%%
-demonitor(Mref) ->
- erlang:demonitor(Mref),
- receive {'DOWN',Mref,_,_,_} -> ok
- after 0 -> ok
- end.
-
%% Fix stacktrace - keep all above call to this module.
%%
stacktrace_f([]) -> [];
diff --git a/lib/et/src/et_collector.erl b/lib/et/src/et_collector.erl
index a63d15fb4c..ce8cf6d4e0 100644
--- a/lib/et/src/et_collector.erl
+++ b/lib/et/src/et_collector.erl
@@ -654,13 +654,8 @@ start_trace_client(CollectorPid, Type, FileName) when Type =:= file ->
Ref = erlang:monitor(process, Pid),
receive
WaitFor ->
- erlang:demonitor(Ref),
- receive
- {'DOWN', Ref, _, _, _} ->
- file_loaded
- after 0 ->
- file_loaded
- end;
+ erlang:demonitor(Ref, [flush]),
+ file_loaded;
{'DOWN', Ref, _, _, Reason} ->
exit(Reason)
end;
diff --git a/lib/kernel/src/application_master.erl b/lib/kernel/src/application_master.erl
index 679fefaed9..34a3efcaf2 100644
--- a/lib/kernel/src/application_master.erl
+++ b/lib/kernel/src/application_master.erl
@@ -76,13 +76,8 @@ call(AppMaster, Req) ->
{'DOWN', Ref, process, _, _Info} ->
ok;
{Tag, Res} ->
- erlang:demonitor(Ref),
- receive
- {'DOWN', Ref, process, _, _Info} ->
- Res
- after 0 ->
- Res
- end
+ erlang:demonitor(Ref, [flush]),
+ Res
end.
%%%-----------------------------------------------------------------
diff --git a/lib/kernel/src/disk_log.erl b/lib/kernel/src/disk_log.erl
index 0c5af2857e..c238eff12f 100644
--- a/lib/kernel/src/disk_log.erl
+++ b/lib/kernel/src/disk_log.erl
@@ -1914,13 +1914,8 @@ multi_req(Msg, Pids) ->
{'DOWN', Ref, process, Pid, _Info} ->
Reply;
{disk_log, Pid, _Reply} ->
- erlang:demonitor(Ref),
- receive
- {'DOWN', Ref, process, Pid, _Reason} ->
- ok
- after 0 ->
- ok
- end
+ erlang:demonitor(Ref, [flush]),
+ ok
end
end, {error, nonode}, Refs).
@@ -1965,13 +1960,8 @@ monitor_request(Pid, Req) ->
{error, no_such_log};
{disk_log, Pid, Reply} when not is_tuple(Reply) orelse
element(2, Reply) =/= disk_log_stopped ->
- erlang:demonitor(Ref),
- receive
- {'DOWN', Ref, process, Pid, _Reason} ->
- Reply
- after 0 ->
- Reply
- end
+ erlang:demonitor(Ref, [flush]),
+ Reply
end.
req2(Pid, R) ->
diff --git a/lib/kernel/src/file.erl b/lib/kernel/src/file.erl
index a4c56b346f..36289053eb 100644
--- a/lib/kernel/src/file.erl
+++ b/lib/kernel/src/file.erl
@@ -480,8 +480,7 @@ open(Item, Mode) ->
Reason :: posix() | badarg | terminated.
close(File) when is_pid(File) ->
- R = file_request(File, close),
- case wait_file_reply(File, R) of
+ case file_request(File, close) of
{error, terminated} ->
ok;
Other ->
@@ -503,8 +502,7 @@ close(_) ->
Reason :: posix() | badarg.
advise(File, Offset, Length, Advise) when is_pid(File) ->
- R = file_request(File, {advise, Offset, Length, Advise}),
- wait_file_reply(File, R);
+ file_request(File, {advise, Offset, Length, Advise});
advise(#file_descriptor{module = Module} = Handle, Offset, Length, Advise) ->
Module:advise(Handle, Offset, Length, Advise);
advise(_, _, _, _) ->
@@ -517,8 +515,7 @@ advise(_, _, _, _) ->
Length :: non_neg_integer().
allocate(File, Offset, Length) when is_pid(File) ->
- R = file_request(File, {allocate, Offset, Length}),
- wait_file_reply(File, R);
+ file_request(File, {allocate, Offset, Length});
allocate(#file_descriptor{module = Module} = Handle, Offset, Length) ->
Module:allocate(Handle, Offset, Length).
@@ -601,8 +598,7 @@ pread_int(_, _, _) ->
Reason :: posix() | badarg | terminated.
pread(File, At, Sz) when is_pid(File), is_integer(Sz), Sz >= 0 ->
- R = file_request(File, {pread, At, Sz}),
- wait_file_reply(File, R);
+ file_request(File, {pread, At, Sz});
pread(#file_descriptor{module = Module} = Handle, Offs, Sz)
when is_integer(Sz), Sz >= 0 ->
Module:pread(Handle, Offs, Sz);
@@ -658,8 +654,7 @@ pwrite_int(_, _, _) ->
Reason :: posix() | badarg | terminated.
pwrite(File, At, Bytes) when is_pid(File) ->
- R = file_request(File, {pwrite, At, Bytes}),
- wait_file_reply(File, R);
+ file_request(File, {pwrite, At, Bytes});
pwrite(#file_descriptor{module = Module} = Handle, Offs, Bytes) ->
Module:pwrite(Handle, Offs, Bytes);
pwrite(_, _, _) ->
@@ -670,8 +665,7 @@ pwrite(_, _, _) ->
Reason :: posix() | badarg | terminated.
datasync(File) when is_pid(File) ->
- R = file_request(File, datasync),
- wait_file_reply(File, R);
+ file_request(File, datasync);
datasync(#file_descriptor{module = Module} = Handle) ->
Module:datasync(Handle);
datasync(_) ->
@@ -682,8 +676,7 @@ datasync(_) ->
Reason :: posix() | badarg | terminated.
sync(File) when is_pid(File) ->
- R = file_request(File, sync),
- wait_file_reply(File, R);
+ file_request(File, sync);
sync(#file_descriptor{module = Module} = Handle) ->
Module:sync(Handle);
sync(_) ->
@@ -696,8 +689,7 @@ sync(_) ->
Reason :: posix() | badarg | terminated.
position(File, At) when is_pid(File) ->
- R = file_request(File, {position,At}),
- wait_file_reply(File, R);
+ file_request(File, {position,At});
position(#file_descriptor{module = Module} = Handle, At) ->
Module:position(Handle, At);
position(_, _) ->
@@ -708,8 +700,7 @@ position(_, _) ->
Reason :: posix() | badarg | terminated.
truncate(File) when is_pid(File) ->
- R = file_request(File, truncate),
- wait_file_reply(File, R);
+ file_request(File, truncate);
truncate(#file_descriptor{module = Module} = Handle) ->
Module:truncate(Handle);
truncate(_) ->
@@ -1497,25 +1488,19 @@ check_args([]) ->
ok.
%%-----------------------------------------------------------------
-%% Functions for communicating with a file io server.
+%% Function for communicating with a file io server.
%% The messages sent have the following formats:
%%
%% {file_request,From,ReplyAs,Request}
%% {file_reply,ReplyAs,Reply}
file_request(Io, Request) ->
- R = erlang:monitor(process, Io),
- Io ! {file_request,self(),Io,Request},
- R.
-
-wait_file_reply(From, Ref) ->
+ Ref = erlang:monitor(process, Io),
+ Io ! {file_request,self(),Ref,Request},
receive
- {file_reply,From,Reply} ->
- erlang:demonitor(Ref),
- receive {'DOWN', Ref, _, _, _} -> ok after 0 -> ok end,
- %% receive {'EXIT', From, _} -> ok after 0 -> ok end,
+ {file_reply,Ref,Reply} ->
+ erlang:demonitor(Ref, [flush]),
Reply;
{'DOWN', Ref, _, _, _} ->
- %% receive {'EXIT', From, _} -> ok after 0 -> ok end,
{error, terminated}
end.
diff --git a/lib/kernel/src/file_io_server.erl b/lib/kernel/src/file_io_server.erl
index fad2ed7fb3..07fb55f390 100644
--- a/lib/kernel/src/file_io_server.erl
+++ b/lib/kernel/src/file_io_server.erl
@@ -92,8 +92,7 @@ do_start(Spawn, Owner, FileName, ModeList) ->
Mref = erlang:monitor(process, Pid),
receive
{Ref, {error, _Reason} = Error} ->
- erlang:demonitor(Mref),
- receive {'DOWN', Mref, _, _, _} -> ok after 0 -> ok end,
+ erlang:demonitor(Mref, [flush]),
Error;
{Ref, ok} ->
erlang:demonitor(Mref),
diff --git a/lib/kernel/src/file_server.erl b/lib/kernel/src/file_server.erl
index 49ec6f96cc..d036dbb516 100644
--- a/lib/kernel/src/file_server.erl
+++ b/lib/kernel/src/file_server.erl
@@ -317,8 +317,7 @@ do_start_slave(start, Filer, Name) ->
SlaveMonitor = erlang:monitor(process, Slave),
receive
{started, Token} ->
- erlang:demonitor(SlaveMonitor),
- receive {'DOWN', SlaveMonitor, _, _, _} -> ok after 0 -> ok end,
+ erlang:demonitor(SlaveMonitor, [flush]),
{ok, Slave};
{'DOWN', SlaveMonitor, _, _, Reason} ->
exit(Reason)
diff --git a/lib/kernel/src/inet_gethost_native.erl b/lib/kernel/src/inet_gethost_native.erl
index db3e44ce6f..df866660b4 100644
--- a/lib/kernel/src/inet_gethost_native.erl
+++ b/lib/kernel/src/inet_gethost_native.erl
@@ -503,8 +503,7 @@ getit(Req, DefaultName) ->
Pid, Reason} ->
{error, Reason}
end,
- catch erlang:demonitor(Ref2),
- receive {'DOWN',Ref2,_,_,_} -> ok after 0 -> ok end,
+ catch erlang:demonitor(Ref2, [flush]),
Res2
end.
diff --git a/lib/kernel/src/rpc.erl b/lib/kernel/src/rpc.erl
index 7c965ca384..83e0b59cc2 100644
--- a/lib/kernel/src/rpc.erl
+++ b/lib/kernel/src/rpc.erl
@@ -388,13 +388,8 @@ server_call(Node, Name, ReplyWrapper, Msg)
{'DOWN', Ref, _, _, _} ->
{error, nodedown};
{ReplyWrapper, Node, Reply} ->
- erlang:demonitor(Ref),
- receive
- {'DOWN', Ref, _, _, _} ->
- Reply
- after 0 ->
- Reply
- end
+ erlang:demonitor(Ref, [flush]),
+ Reply
end
end.
@@ -501,17 +496,6 @@ start_monitor(Node, Name) ->
{Node,erlang:monitor(process, {Name, Node})}
end.
-%% Cancels a monitor started with Ref=erlang:monitor(_, _),
-%% i.e return value {Node, Ref} from start_monitor/2 above.
-unmonitor(Ref) when is_reference(Ref) ->
- erlang:demonitor(Ref),
- receive
- {'DOWN', Ref, _, _, _} ->
- true
- after 0 ->
- true
- end.
-
%% Call apply(M,F,A) on all nodes in parallel
-spec multicall(Module, Function, Args) -> {ResL, BadNodes} when
@@ -635,10 +619,10 @@ rec_nodes(Name, [{N,R} | Tail], Badnodes, Replies) ->
rec_nodes(Name, Tail, [N|Badnodes], Replies);
{?NAME, N, {nonexisting_name, _}} ->
%% used by sbcast()
- unmonitor(R),
+ erlang:demonitor(R, [flush]),
rec_nodes(Name, Tail, [N|Badnodes], Replies);
{Name, N, Reply} -> %% Name is bound !!!
- unmonitor(R),
+ erlang:demonitor(R, [flush]),
rec_nodes(Name, Tail, Badnodes, [Reply|Replies])
end.
diff --git a/lib/kernel/test/file_SUITE.erl b/lib/kernel/test/file_SUITE.erl
index c604e7073f..4218cfa646 100644
--- a/lib/kernel/test/file_SUITE.erl
+++ b/lib/kernel/test/file_SUITE.erl
@@ -91,6 +91,8 @@
-export([standard_io/1,mini_server/1]).
+-export([old_io_protocol/1]).
+
%% Debug exports
-export([create_file_slow/2, create_file/2, create_bin/2]).
-export([verify_file/2, verify_bin/3]).
@@ -114,7 +116,7 @@ all() ->
delayed_write, read_ahead, segment_read, segment_write,
ipread, pid2name, interleaved_read_write, otp_5814, otp_10852,
large_file, large_write, read_line_1, read_line_2, read_line_3,
- read_line_4, standard_io].
+ read_line_4, standard_io, old_io_protocol].
groups() ->
[{dirs, [], [make_del_dir, cur_dir_0, cur_dir_1,
@@ -310,6 +312,31 @@ standard_io(Config) when is_list(Config) ->
Pid ! die,
receive after 1000 -> ok end.
+old_io_protocol(suite) ->
+ [];
+old_io_protocol(doc) ->
+ ["Test that the old file IO protocol =< R16B still works"];
+old_io_protocol(Config) when is_list(Config) ->
+ Dog = test_server:timetrap(test_server:seconds(5)),
+ RootDir = ?config(priv_dir,Config),
+ Name = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"old_io_protocol.fil"),
+ MyData = "0123456789abcdefghijklmnopqrstuvxyz",
+ ok = ?FILE_MODULE:write_file(Name, MyData),
+ {ok, Fd} = ?FILE_MODULE:open(Name, write),
+ Fd ! {file_request,self(),Fd,truncate},
+ receive
+ {file_reply,Fd,ok} -> ok
+ end,
+ ok = ?FILE_MODULE:close(Fd),
+ {ok, <<>>} = ?FILE_MODULE:read_file(Name),
+ test_server:timetrap_cancel(Dog),
+ [] = flush(),
+ ok.
+
+
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
read_write_file(suite) -> [];
diff --git a/lib/kernel/test/gen_sctp_SUITE.erl b/lib/kernel/test/gen_sctp_SUITE.erl
index 2a886b2efc..c5d8becfd3 100644
--- a/lib/kernel/test/gen_sctp_SUITE.erl
+++ b/lib/kernel/test/gen_sctp_SUITE.erl
@@ -1399,8 +1399,7 @@ s_req(S, Req) ->
{'DOWN',Mref,_,_,Error} ->
exit(Error);
{S,Mref,Reply} ->
- erlang:demonitor(Mref),
- receive {'DOWN',Mref,_,_,_} -> ok after 0 -> ok end,
+ erlang:demonitor(Mref, [flush]),
Reply
end.
diff --git a/lib/orber/src/orber_iiop_outproxy.erl b/lib/orber/src/orber_iiop_outproxy.erl
index 879af8222d..9c4e603753 100644
--- a/lib/orber/src/orber_iiop_outproxy.erl
+++ b/lib/orber/src/orber_iiop_outproxy.erl
@@ -69,13 +69,8 @@ request(Pid, true, Timeout, Msg, RequestId) ->
gen_server:cast(Pid, {request, Timeout, Msg, RequestId, self(), MRef}),
receive
{MRef, Reply} ->
- erlang:demonitor(MRef),
- receive
- {'DOWN', MRef, _, _, _} ->
- Reply
- after 0 ->
- Reply
- end;
+ erlang:demonitor(MRef, [flush]),
+ Reply;
{'DOWN', MRef, _, Pid, _Reason} when is_pid(Pid) ->
receive
%% Clear EXIT message from queue
@@ -444,13 +439,7 @@ collect_fragments(GIOPHdr1, InBuffer, Bytes, Proxy, RequestId, MRef) ->
%% the reply and send it to the client.
{fragment, #giop_message{byte_order = ByteOrder,
message = Message} = GIOPHdr2, RequestId, MRef} ->
- erlang:demonitor(MRef),
- receive
- {'DOWN', MRef, _, _, _} ->
- ok
- after 0 ->
- ok
- end,
+ erlang:demonitor(MRef, [flush]),
case catch cdr_decode:dec_message_header(null, GIOPHdr2, Message) of
{_, #fragment_header{}, FragBody, _, _} ->
%% This buffer is all the fragments concatenated.
@@ -484,13 +473,8 @@ Unable to decode Reply or LocateReply header",[?LINE, NewGIOP, Error], ?DEBUG_LE
{MRef, {'EXCEPTION', E}} ->
orber:dbg("[~p] orber_iiop:collect_fragments(~p);",
[?LINE, E], ?DEBUG_LEVEL),
- erlang:demonitor(MRef),
- receive
- {'DOWN', MRef, _, _, _} ->
- corba:raise(E)
- after 0 ->
- corba:raise(E)
- end;
+ erlang:demonitor(MRef, [flush]),
+ corba:raise(E);
{'DOWN', MRef, _, Proxy, Reason} when is_pid(Proxy) ->
orber:dbg("[~p] orber_iiop:collect_fragments(~p);~n"
"Monitor generated a DOWN message.",
@@ -511,13 +495,8 @@ clear_queue(Proxy, RequestId, MRef) ->
{MRef, RequestId, cancelled} ->
%% This is the last message that the proxy will send
%% after we've cancelled the request.
- erlang:demonitor(MRef),
- receive
- {'DOWN', MRef, _, _, _} ->
- ok
- after 0 ->
- ok
- end;
+ erlang:demonitor(MRef, [flush]),
+ ok;
{'DOWN', MRef, _, Proxy, _Reason} ->
%% The proxy terminated. Clear EXIT message from queue
receive
diff --git a/lib/runtime_tools/src/dbg.erl b/lib/runtime_tools/src/dbg.erl
index 6e3bfe31c6..6b2fb0460f 100644
--- a/lib/runtime_tools/src/dbg.erl
+++ b/lib/runtime_tools/src/dbg.erl
@@ -551,8 +551,7 @@ c(M, F, A, Flags) ->
stop_clear(),
{error, Reason};
{Pid, Res} ->
- erlang:demonitor(Mref),
- receive {'DOWN', Mref, _, _, _} -> ok after 0 -> ok end,
+ erlang:demonitor(Mref, [flush]),
%% 'sleep' prevents the tracer (recv_all_traces) from
%% receiving garbage {'EXIT',...} when dbg i stopped.
timer:sleep(1),
@@ -592,8 +591,7 @@ req(R) ->
{'DOWN', Mref, _, _, _} -> % If server died
exit(dbg_server_crash);
{dbg, Reply} ->
- erlang:demonitor(Mref),
- receive {'DOWN', Mref, _, _, _} -> ok after 0 -> ok end,
+ erlang:demonitor(Mref, [flush]),
Reply
end.
diff --git a/lib/snmp/src/agent/snmpa_target_cache.erl b/lib/snmp/src/agent/snmpa_target_cache.erl
index 2aa35aa46a..1fcaf82373 100644
--- a/lib/snmp/src/agent/snmpa_target_cache.erl
+++ b/lib/snmp/src/agent/snmpa_target_cache.erl
@@ -21,8 +21,6 @@
-behaviour(gen_server).
%% External exports
-%% Avoid warning for local function demonitor/1 clashing with autoimported BIF.
--compile({no_auto_import,[demonitor/1]}).
-export([start_link/2, stop/0, verbosity/1]).
-export([
@@ -213,21 +211,6 @@ do_init(Prio, Opts) ->
%% requests will have to wait.
%%
-monitor(Pid) -> erlang:monitor(process, Pid).
--ifdef(SNMP_R10).
-demonitor(Ref) ->
- erlang:demonitor(Ref),
- receive
- {_, Ref, _, _, _} ->
- true
- after 0 ->
- true
- end.
--else.
-demonitor(Ref) ->
- erlang:demonitor(Ref, [flush]).
--endif.
-
%% (1) No write_lock active or waiting
handle_call({lock, read = Type, infinity}, {Pid, _} = From,
@@ -236,7 +219,7 @@ handle_call({lock, read = Type, infinity}, {Pid, _} = From,
"entry when no waiting or active writer with"
"~n Pid: ~p"
"~n Cnt: ~p", [Pid, Cnt]),
- MonRef = monitor(Pid),
+ MonRef = erlang:monitor(process, Pid),
Locker = #locker{pid = Pid,
from = From,
mon_ref = MonRef,
@@ -252,7 +235,7 @@ handle_call({lock, read = Type, infinity}, {Pid, _} = From, State) ->
?vlog("lock(read, infinity) -> "
"entry when active or waiting write locks with"
"~n Pid: ~p", [Pid]),
- MonRef = monitor(Pid),
+ MonRef = erlang:monitor(process, Pid),
Locker = #locker{pid = Pid,
from = From,
mon_ref = MonRef,
@@ -273,7 +256,7 @@ handle_call({lock, write = Type, infinity}, {Pid, _} = From,
?vlog("lock(write, infinity) -> "
"entry when no active lockers with"
"~n Pid: ~p", [Pid]),
- MonRef = monitor(Pid),
+ MonRef = erlang:monitor(process, Pid),
Locker = #locker{pid = Pid,
from = From,
mon_ref = MonRef,
@@ -290,7 +273,7 @@ handle_call({lock, write = Type, infinity}, {Pid, _} = From,
?vlog("lock(write, infinity) -> "
"entry when active lockers with"
"~n Pid: ~p", [Pid]),
- MonRef = monitor(Pid),
+ MonRef = erlang:monitor(process, Pid),
Locker = #locker{pid = Pid,
from = From,
mon_ref = MonRef,
@@ -307,7 +290,7 @@ handle_call({lock, write = Type, infinity}, {Pid, _} = From,
#state{writer = true} = State) ->
?vlog("lock(write, infinity) -> entry with"
"~n Pid: ~p", [Pid]),
- MonRef = monitor(Pid),
+ MonRef = erlang:monitor(process, Pid),
Locker = #locker{pid = Pid,
from = From,
mon_ref = MonRef,
@@ -429,7 +412,7 @@ handle_cast({unlock, Pid},
[#locker{mon_ref = MonRef, type = read}] ->
?vdebug("unlock -> found read locker"
"~n MonRef: ~p", [MonRef]),
- demonitor(MonRef),
+ erlang:demonitor(MonRef, [flush]),
ets:delete(?LOCKER_TAB, Pid),
%% ?vtrace("unlock -> done when"
%% "~n Lockers: ~p", [ets:tab2list(?LOCKER_TAB)]),
@@ -437,7 +420,7 @@ handle_cast({unlock, Pid},
[#locker{mon_ref = MonRef, type = write}] ->
?vdebug("unlock -> found write locker"
"~n MonRef: ~p", [MonRef]),
- demonitor(MonRef),
+ erlang:demonitor(MonRef, [flush]),
ets:delete(?LOCKER_TAB, Pid),
%% ?vtrace("unlock -> done when"
%% "~n Lockers: ~p", [ets:tab2list(?LOCKER_TAB)]),
@@ -459,7 +442,7 @@ handle_cast({unlock, Pid},
[#locker{mon_ref = MonRef, type = read}] when (Cnt == 1) ->
?vdebug("unlock -> found read locker"
"~n MonRef: ~p", [MonRef]),
- demonitor(MonRef),
+ erlang:demonitor(MonRef, [flush]),
ets:delete(?LOCKER_TAB, Pid),
case active_waiting_writer(Waiting) of
{true, StillWaiting} ->
@@ -482,7 +465,7 @@ handle_cast({unlock, Pid},
[#locker{mon_ref = MonRef, type = read}] ->
?vdebug("unlock -> found read locker"
"~n MonRef: ~p", [MonRef]),
- demonitor(MonRef),
+ erlang:demonitor(MonRef, [flush]),
ets:delete(?LOCKER_TAB, Pid),
%% ?vtrace("unlock -> done when"
%% "~n Lockers: ~p", [ets:tab2list(?LOCKER_TAB)]),
@@ -492,7 +475,7 @@ handle_cast({unlock, Pid},
%% Release the hord (maybe)
?vdebug("unlock -> found write locker"
"~n MonRef: ~p", [MonRef]),
- demonitor(MonRef),
+ erlang:demonitor(MonRef, [flush]),
ets:delete(?LOCKER_TAB, Pid),
{Active, StillWaiting, Writer} =
activate_waiting_readers_or_maybe_writer(Waiting),
diff --git a/lib/stdlib/src/dets.erl b/lib/stdlib/src/dets.erl
index 45aef0ea80..50812cc532 100644
--- a/lib/stdlib/src/dets.erl
+++ b/lib/stdlib/src/dets.erl
@@ -1246,13 +1246,8 @@ req(Proc, R) ->
{'DOWN', Ref, process, Proc, _Info} ->
badarg;
{Proc, Reply} ->
- erlang:demonitor(Ref),
- receive
- {'DOWN', Ref, process, Proc, _Reason} ->
- Reply
- after 0 ->
- Reply
- end
+ erlang:demonitor(Ref, [flush]),
+ Reply
end.
%% Inlined.
diff --git a/lib/stdlib/src/epp.erl b/lib/stdlib/src/epp.erl
index 0a1caa7178..e31cd63f69 100644
--- a/lib/stdlib/src/epp.erl
+++ b/lib/stdlib/src/epp.erl
@@ -1339,8 +1339,7 @@ epp_reply(From, Rep) ->
wait_epp_reply(Epp, Mref) ->
receive
{epp_reply,Epp,Rep} ->
- erlang:demonitor(Mref),
- receive {'DOWN',Mref,_,_,_} -> ok after 0 -> ok end,
+ erlang:demonitor(Mref, [flush]),
Rep;
{'DOWN',Mref,_,_,E} ->
receive {epp_reply,Epp,Rep} -> Rep
diff --git a/lib/stdlib/src/gen_server.erl b/lib/stdlib/src/gen_server.erl
index 9c4b95acf6..30a81ade49 100644
--- a/lib/stdlib/src/gen_server.erl
+++ b/lib/stdlib/src/gen_server.erl
@@ -472,11 +472,11 @@ rec_nodes(Tag, [{N,R}|Tail], Name, Badnodes, Replies, Time, TimerId ) ->
{'DOWN', R, _, _, _} ->
rec_nodes(Tag, Tail, Name, [N|Badnodes], Replies, Time, TimerId);
{{Tag, N}, Reply} -> %% Tag is bound !!!
- unmonitor(R),
+ erlang:demonitor(R, [flush]),
rec_nodes(Tag, Tail, Name, Badnodes,
[{N,Reply}|Replies], Time, TimerId);
{timeout, TimerId, _} ->
- unmonitor(R),
+ erlang:demonitor(R, [flush]),
%% Collect all replies that already have arrived
rec_nodes_rest(Tag, Tail, Name, [N|Badnodes], Replies)
end;
@@ -527,10 +527,10 @@ rec_nodes_rest(Tag, [{N,R}|Tail], Name, Badnodes, Replies) ->
{'DOWN', R, _, _, _} ->
rec_nodes_rest(Tag, Tail, Name, [N|Badnodes], Replies);
{{Tag, N}, Reply} -> %% Tag is bound !!!
- unmonitor(R),
+ erlang:demonitor(R, [flush]),
rec_nodes_rest(Tag, Tail, Name, Badnodes, [{N,Reply}|Replies])
after 0 ->
- unmonitor(R),
+ erlang:demonitor(R, [flush]),
rec_nodes_rest(Tag, Tail, Name, [N|Badnodes], Replies)
end;
rec_nodes_rest(Tag, [N|Tail], Name, Badnodes, Replies) ->
@@ -572,16 +572,6 @@ start_monitor(Node, Name) when is_atom(Node), is_atom(Name) ->
end
end.
-%% Cancels a monitor started with Ref=erlang:monitor(_, _).
-unmonitor(Ref) when is_reference(Ref) ->
- erlang:demonitor(Ref),
- receive
- {'DOWN', Ref, _, _, _} ->
- true
- after 0 ->
- true
- end.
-
%%% ---------------------------------------------------
%%% Message handling functions
%%% ---------------------------------------------------
diff --git a/lib/stdlib/src/io.erl b/lib/stdlib/src/io.erl
index c92e9e3ade..53728237ca 100644
--- a/lib/stdlib/src/io.erl
+++ b/lib/stdlib/src/io.erl
@@ -598,11 +598,7 @@ default_output() ->
wait_io_mon_reply(From, Mref) ->
receive
{io_reply, From, Reply} ->
- erlang:demonitor(Mref),
- receive
- {'DOWN', Mref, _, _, _} -> true
- after 0 -> true
- end,
+ erlang:demonitor(Mref, [flush]),
Reply;
{'EXIT', From, _What} ->
receive
diff --git a/lib/stdlib/src/supervisor.erl b/lib/stdlib/src/supervisor.erl
index 9f93747c3e..54328cd9ff 100644
--- a/lib/stdlib/src/supervisor.erl
+++ b/lib/stdlib/src/supervisor.erl
@@ -63,7 +63,9 @@
%%--------------------------------------------------------------------------
-record(child, {% pid is undefined when child is not running
- pid = undefined :: child() | {restarting,pid()} | [pid()],
+ pid = undefined :: child()
+ | {restarting, pid() | undefined}
+ | [pid()],
name :: child_id(),
mfargs :: mfargs(),
restart_type :: restart(),
@@ -752,6 +754,9 @@ restart(Child, State) ->
end,
timer:apply_after(0,?MODULE,try_again_restart,[self(),Id]),
{ok,NState2};
+ {try_again, NState2, #child{name=ChName}} ->
+ timer:apply_after(0,?MODULE,try_again_restart,[self(),ChName]),
+ {ok,NState2};
Other ->
Other
end;
@@ -798,10 +803,16 @@ restart(rest_for_one, Child, State) ->
case start_children(ChAfter2, State#state.name) of
{ok, ChAfter3} ->
{ok, State#state{children = ChAfter3 ++ ChBefore}};
- {error, ChAfter3, _Reason} ->
+ {error, ChAfter3, {failed_to_start_child, ChName, _Reason}}
+ when ChName =:= Child#child.name ->
NChild = Child#child{pid=restarting(Child#child.pid)},
NState = State#state{children = ChAfter3 ++ ChBefore},
- {try_again, replace_child(NChild,NState)}
+ {try_again, replace_child(NChild,NState)};
+ {error, ChAfter3, {failed_to_start_child, ChName, _Reason}} ->
+ NChild = lists:keyfind(ChName, #child.name, ChAfter3),
+ NChild2 = NChild#child{pid=?restarting(undefined)},
+ NState = State#state{children = ChAfter3 ++ ChBefore},
+ {try_again, replace_child(NChild2,NState), NChild2}
end;
restart(one_for_all, Child, State) ->
Children1 = del_child(Child#child.pid, State#state.children),
@@ -809,10 +820,16 @@ restart(one_for_all, Child, State) ->
case start_children(Children2, State#state.name) of
{ok, NChs} ->
{ok, State#state{children = NChs}};
- {error, NChs, _Reason} ->
+ {error, NChs, {failed_to_start_child, ChName, _Reason}}
+ when ChName =:= Child#child.name ->
NChild = Child#child{pid=restarting(Child#child.pid)},
NState = State#state{children = NChs},
- {try_again, replace_child(NChild,NState)}
+ {try_again, replace_child(NChild,NState)};
+ {error, NChs, {failed_to_start_child, ChName, _Reason}} ->
+ NChild = lists:keyfind(ChName, #child.name, NChs),
+ NChild2 = NChild#child{pid=?restarting(undefined)},
+ NState = State#state{children = NChs},
+ {try_again, replace_child(NChild2,NState), NChild2}
end.
restarting(Pid) when is_pid(Pid) -> ?restarting(Pid);
diff --git a/lib/stdlib/test/Makefile b/lib/stdlib/test/Makefile
index 6aa09d7bd0..af82f22b21 100644
--- a/lib/stdlib/test/Makefile
+++ b/lib/stdlib/test/Makefile
@@ -66,6 +66,7 @@ MODULES= \
string_SUITE \
supervisor_1 \
supervisor_2 \
+ supervisor_3 \
supervisor_deadlock \
naughty_child \
shell_SUITE \
diff --git a/lib/stdlib/test/supervisor_3.erl b/lib/stdlib/test/supervisor_3.erl
new file mode 100644
index 0000000000..31b3037d6f
--- /dev/null
+++ b/lib/stdlib/test/supervisor_3.erl
@@ -0,0 +1,45 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1996-2011. 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%
+%%
+%% Description: Simulates the behaviour that a child process may have.
+%% Is used by the supervisor_SUITE test suite.
+-module(supervisor_3).
+
+-export([start_child/2, init/1]).
+
+-export([handle_call/3, handle_info/2, terminate/2]).
+
+start_child(Name, Caller) ->
+ gen_server:start_link(?MODULE, [Name, Caller], []).
+
+init([Name, Caller]) ->
+ Caller ! {Name, self()},
+ receive
+ {Result, Caller} ->
+ Result
+ end.
+
+handle_call(Req, _From, State) ->
+ {reply, Req, State}.
+
+handle_info(_, State) ->
+ {noreply, State}.
+
+terminate(_Reason, Time) ->
+ timer:sleep(Time),
+ ok.
diff --git a/lib/stdlib/test/supervisor_SUITE.erl b/lib/stdlib/test/supervisor_SUITE.erl
index 569c66959e..ff5be6bb95 100644
--- a/lib/stdlib/test/supervisor_SUITE.erl
+++ b/lib/stdlib/test/supervisor_SUITE.erl
@@ -53,9 +53,10 @@
%% Restart strategy tests
-export([ one_for_one/1,
one_for_one_escalation/1, one_for_all/1,
- one_for_all_escalation/1,
+ one_for_all_escalation/1, one_for_all_other_child_fails_restart/1,
simple_one_for_one/1, simple_one_for_one_escalation/1,
rest_for_one/1, rest_for_one_escalation/1,
+ rest_for_one_other_child_fails_restart/1,
simple_one_for_one_extra/1, simple_one_for_one_shutdown/1]).
%% Misc tests
@@ -107,12 +108,14 @@ groups() ->
{restart_one_for_one, [],
[one_for_one, one_for_one_escalation]},
{restart_one_for_all, [],
- [one_for_all, one_for_all_escalation]},
+ [one_for_all, one_for_all_escalation,
+ one_for_all_other_child_fails_restart]},
{restart_simple_one_for_one, [],
[simple_one_for_one, simple_one_for_one_shutdown,
simple_one_for_one_extra, simple_one_for_one_escalation]},
{restart_rest_for_one, [],
- [rest_for_one, rest_for_one_escalation]}].
+ [rest_for_one, rest_for_one_escalation,
+ rest_for_one_other_child_fails_restart]}].
init_per_suite(Config) ->
Config.
@@ -879,6 +882,57 @@ one_for_all_escalation(Config) when is_list(Config) ->
%%-------------------------------------------------------------------------
+%% Test that the supervisor terminates a restarted child when a different
+%% child fails to start.
+one_for_all_other_child_fails_restart(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ Self = self(),
+ Child1 = {child1, {supervisor_3, start_child, [child1, Self]},
+ permanent, 1000, worker, []},
+ Child2 = {child2, {supervisor_3, start_child, [child2, Self]},
+ permanent, 1000, worker, []},
+ Children = [Child1, Child2],
+ StarterFun = fun() ->
+ {ok, SupPid} = start_link({ok, {{one_for_all, 3, 3600}, Children}}),
+ Self ! {sup_pid, SupPid},
+ receive {stop, Self} -> ok end
+ end,
+ StarterPid = spawn_link(StarterFun),
+ Ok = {{ok, undefined}, Self},
+ %% Let the children start.
+ Child1Pid = receive {child1, Pid1} -> Pid1 end,
+ Child1Pid ! Ok,
+ Child2Pid = receive {child2, Pid2} -> Pid2 end,
+ Child2Pid ! Ok,
+ %% Supervisor started.
+ SupPid = receive {sup_pid, Pid} -> Pid end,
+ link(SupPid),
+ exit(Child1Pid, die),
+ %% Let child1 restart but don't let child2.
+ Child1Pid2 = receive {child1, Pid3} -> Pid3 end,
+ Child1Pid2Ref = erlang:monitor(process, Child1Pid2),
+ Child1Pid2 ! Ok,
+ Child2Pid2 = receive {child2, Pid4} -> Pid4 end,
+ Child2Pid2 ! {{stop, normal}, Self},
+ %% Check child1 is terminated.
+ receive
+ {'DOWN', Child1Pid2Ref, _, _, shutdown} ->
+ ok;
+ {_childName, _Pid} ->
+ exit(SupPid, kill),
+ check_exit([StarterPid, SupPid]),
+ test_server:fail({restarting_child_not_terminated, Child1Pid2})
+ end,
+ %% Let the restart complete.
+ Child1Pid3 = receive {child1, Pid5} -> Pid5 end,
+ Child1Pid3 ! Ok,
+ Child2Pid3 = receive {child2, Pid6} -> Pid6 end,
+ Child2Pid3 ! Ok,
+ StarterPid ! {stop, Self},
+ check_exit([StarterPid, SupPid]).
+
+
+%%-------------------------------------------------------------------------
%% Test the simple_one_for_one base case.
simple_one_for_one(Config) when is_list(Config) ->
process_flag(trap_exit, true),
@@ -1044,6 +1098,52 @@ rest_for_one_escalation(Config) when is_list(Config) ->
terminate(SupPid, CPid1, child1, abnormal),
check_exit([CPid2, SupPid]).
+
+%%-------------------------------------------------------------------------
+%% Test that the supervisor terminates a restarted child when a different
+%% child fails to start.
+rest_for_one_other_child_fails_restart(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ Self = self(),
+ Child1 = {child1, {supervisor_3, start_child, [child1, Self]},
+ permanent, 1000, worker, []},
+ Child2 = {child2, {supervisor_3, start_child, [child2, Self]},
+ permanent, 1000, worker, []},
+ Children = [Child1, Child2],
+ StarterFun = fun() ->
+ {ok, SupPid} = start_link({ok, {{rest_for_one, 3, 3600}, Children}}),
+ Self ! {sup_pid, SupPid},
+ receive {stop, Self} -> ok end
+ end,
+ StarterPid = spawn_link(StarterFun),
+ Ok = {{ok, undefined}, Self},
+ %% Let the children start.
+ Child1Pid = receive {child1, Pid1} -> Pid1 end,
+ Child1Pid ! Ok,
+ Child2Pid = receive {child2, Pid2} -> Pid2 end,
+ Child2Pid ! Ok,
+ %% Supervisor started.
+ SupPid = receive {sup_pid, Pid} -> Pid end,
+ link(SupPid),
+ exit(Child1Pid, die),
+ %% Let child1 restart but don't let child2.
+ Child1Pid2 = receive {child1, Pid3} -> Pid3 end,
+ Child1Pid2 ! Ok,
+ Child2Pid2 = receive {child2, Pid4} -> Pid4 end,
+ Child2Pid2 ! {{stop, normal}, Self},
+ %% Let child2 restart.
+ receive
+ {child2, Child2Pid3} ->
+ Child2Pid3 ! Ok;
+ {child1, _Child1Pid3} ->
+ exit(SupPid, kill),
+ check_exit([StarterPid, SupPid]),
+ test_server:fail({restarting_started_child, Child1Pid2})
+ end,
+ StarterPid ! {stop, Self},
+ check_exit([StarterPid, SupPid]).
+
+
%%-------------------------------------------------------------------------
%% Test that the supervisor does not hang forever if the child unliks
%% and then is terminated by the supervisor.
diff --git a/lib/tools/src/fprof.erl b/lib/tools/src/fprof.erl
index 4cbb910f11..877218bda0 100644
--- a/lib/tools/src/fprof.erl
+++ b/lib/tools/src/fprof.erl
@@ -1226,10 +1226,7 @@ spawn_3step(Spawn, FunPrelude, FunAck, FunBody)
MRef = erlang:monitor(process, Parent),
receive
{Parent, Ref, Go} ->
- erlang:demonitor(MRef),
- receive {'DOWN', MRef, _, _, _} -> ok
- after 0 -> ok
- end,
+ erlang:demonitor(MRef, [flush]),
FunBody(Go);
{'DOWN', MRef, _, _, _} ->
ok
@@ -1238,8 +1235,7 @@ spawn_3step(Spawn, FunPrelude, FunAck, FunBody)
MRef = erlang:monitor(process, Child),
receive
{Child, Ref, Ack} ->
- erlang:demonitor(MRef),
- receive {'DOWN', MRef, _, _, _} -> ok after 0 -> ok end,
+ erlang:demonitor(MRef, [flush]),
try FunAck(Ack) of
{Result, Go} ->
catch Child ! {Parent, Ref, Go},