diff options
author | Dan Gudmundsson <[email protected]> | 2012-10-11 14:52:21 +0200 |
---|---|---|
committer | Dan Gudmundsson <[email protected]> | 2012-10-30 16:14:45 +0100 |
commit | 6fba00f0e0e66311dd3a476aaa0c9d7f288a2a9b (patch) | |
tree | 740b71385f59d07362caef8ff0f77b79e98cce5e /lib/stdlib/src | |
parent | a8b2ba096dc48a29af52fd68070089d4bbb37483 (diff) | |
download | otp-6fba00f0e0e66311dd3a476aaa0c9d7f288a2a9b.tar.gz otp-6fba00f0e0e66311dd3a476aaa0c9d7f288a2a9b.tar.bz2 otp-6fba00f0e0e66311dd3a476aaa0c9d7f288a2a9b.zip |
stdlib: Monitor proc_lib:start'ed processes to avoid waiting forever
Monitor the spawned process in proc_lib:start/[3|4|5], so
that a proper error is returned, if the spawned process crashes
before proclib:init_ack/1 is sent.
Previously the calling process would hang forever or until specified
timeout. Start link catches these errors but start did not.
start now behaves as start_link if process traps exit.
Diffstat (limited to 'lib/stdlib/src')
-rw-r--r-- | lib/stdlib/src/proc_lib.erl | 38 |
1 files changed, 33 insertions, 5 deletions
diff --git a/lib/stdlib/src/proc_lib.erl b/lib/stdlib/src/proc_lib.erl index 02bcbb5a60..4bca4c1e6d 100644 --- a/lib/stdlib/src/proc_lib.erl +++ b/lib/stdlib/src/proc_lib.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2011. All Rights Reserved. +%% Copyright Ericsson AB 1996-2012. 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 @@ -184,6 +184,17 @@ check_for_monitor(SpawnOpts) -> false end. +spawn_mon(M,F,A) -> + Parent = get_my_name(), + Ancestors = get_ancestors(), + erlang:spawn_monitor(?MODULE, init_p, [Parent,Ancestors,M,F,A]). + +spawn_opt_mon(M, F, A, Opts) when is_atom(M), is_atom(F), is_list(A) -> + Parent = get_my_name(), + Ancestors = get_ancestors(), + check_for_monitor(Opts), + erlang:spawn_opt(?MODULE, init_p, [Parent,Ancestors,M,F,A], [monitor|Opts]). + -spec hibernate(Module, Function, Args) -> no_return() when Module :: module(), Function :: atom(), @@ -270,8 +281,8 @@ start(M, F, A) when is_atom(M), is_atom(F), is_list(A) -> Ret :: term() | {error, Reason :: term()}. start(M, F, A, Timeout) when is_atom(M), is_atom(F), is_list(A) -> - Pid = ?MODULE:spawn(M, F, A), - sync_wait(Pid, Timeout). + PidRef = spawn_mon(M, F, A), + sync_wait_mon(PidRef, Timeout). -spec start(Module, Function, Args, Time, SpawnOpts) -> Ret when Module :: module(), @@ -282,8 +293,8 @@ start(M, F, A, Timeout) when is_atom(M), is_atom(F), is_list(A) -> Ret :: term() | {error, Reason :: term()}. start(M, F, A, Timeout, SpawnOpts) when is_atom(M), is_atom(F), is_list(A) -> - Pid = ?MODULE:spawn_opt(M, F, A, SpawnOpts), - sync_wait(Pid, Timeout). + PidRef = spawn_opt_mon(M, F, A, SpawnOpts), + sync_wait_mon(PidRef, Timeout). -spec start_link(Module, Function, Args) -> Ret when Module :: module(), @@ -330,6 +341,23 @@ sync_wait(Pid, Timeout) -> {error, timeout} end. +sync_wait_mon({Pid, Ref}, Timeout) -> + receive + {ack, Pid, Return} -> + erlang:demonitor(Ref, [flush]), + Return; + {'DOWN', Ref, _Type, Pid, Reason} -> + {error, Reason}; + {'EXIT', Pid, Reason} -> %% link as spawn_opt? + erlang:demonitor(Ref, [flush]), + {error, Reason} + after Timeout -> + erlang:demonitor(Ref, [flush]), + exit(Pid, kill), + flush(Pid), + {error, timeout} + end. + -spec flush(pid()) -> 'true'. flush(Pid) -> |