aboutsummaryrefslogtreecommitdiff
path: root/src/p1_fsm.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/p1_fsm.erl')
-rw-r--r--src/p1_fsm.erl70
1 files changed, 63 insertions, 7 deletions
diff --git a/src/p1_fsm.erl b/src/p1_fsm.erl
index 03ff7f8ce..9ca924112 100644
--- a/src/p1_fsm.erl
+++ b/src/p1_fsm.erl
@@ -517,6 +517,25 @@ print_event(Dev, return, {Name, StateName}) ->
io:format(Dev, "*DBG* ~p switched to state ~w~n",
[Name, StateName]).
+relay_messages(MRef, TRef, Clone, Queue) ->
+ lists:foreach(
+ fun(Msg) -> Clone ! Msg end,
+ queue:to_list(Queue)),
+ relay_messages(MRef, TRef, Clone).
+
+relay_messages(MRef, TRef, Clone) ->
+ receive
+ {'DOWN', MRef, process, Clone, Reason} ->
+ Reason;
+ {'EXIT', _Parent, _Reason} ->
+ {migrated, Clone};
+ {timeout, TRef, timeout} ->
+ {migrated, Clone};
+ Msg ->
+ Clone ! Msg,
+ relay_messages(MRef, TRef, Clone)
+ end.
+
handle_msg(Msg, Parent, Name, StateName, StateData, Mod, _Time,
Limits, Queue, QueueLen) -> %No debug here
From = from(Msg),
@@ -535,6 +554,23 @@ handle_msg(Msg, Parent, Name, StateName, StateData, Mod, _Time,
reply(From, Reply),
loop(Parent, Name, NStateName, NStateData, Mod, Time1, [],
Limits, Queue, QueueLen);
+ {migrate, NStateData, {Node, M, F, A}, Time1} ->
+ Reason = case catch rpc:call(Node, M, F, A, 5000) of
+ {badrpc, _} = Err ->
+ {migration_error, Err};
+ {'EXIT', _} = Err ->
+ {migration_error, Err};
+ {error, _} = Err ->
+ {migration_error, Err};
+ {ok, Clone} ->
+ process_flag(trap_exit, true),
+ MRef = erlang:monitor(process, Clone),
+ TRef = erlang:start_timer(Time1, self(), timeout),
+ relay_messages(MRef, TRef, Clone, Queue);
+ Reply ->
+ {migration_error, {bad_reply, Reply}}
+ end,
+ terminate(Reason, Name, Msg, Mod, StateName, NStateData, []);
{stop, Reason, NStateData} ->
terminate(Reason, Name, Msg, Mod, StateName, NStateData, []);
{stop, Reason, Reply, NStateData} when From =/= undefined ->
@@ -571,6 +607,23 @@ handle_msg(Msg, Parent, Name, StateName, StateData,
Debug1 = reply(Name, From, Reply, Debug, NStateName),
loop(Parent, Name, NStateName, NStateData,
Mod, Time1, Debug1, Limits, Queue, QueueLen);
+ {migrate, NStateData, {Node, M, F, A}, Time1} ->
+ Reason = case catch rpc:call(Node, M, F, A, Time1) of
+ {badrpc, R} ->
+ {migration_error, R};
+ {'EXIT', R} ->
+ {migration_error, R};
+ {error, R} ->
+ {migration_error, R};
+ {ok, Clone} ->
+ process_flag(trap_exit, true),
+ MRef = erlang:monitor(process, Clone),
+ TRef = erlang:start_timer(Time1, self(), timeout),
+ relay_messages(MRef, TRef, Clone, Queue);
+ Reply ->
+ {migration_error, {bad_reply, Reply}}
+ end,
+ terminate(Reason, Name, Msg, Mod, StateName, NStateData, Debug);
{stop, Reason, NStateData} ->
terminate(Reason, Name, Msg, Mod, StateName, NStateData, Debug);
{stop, Reason, Reply, NStateData} when From =/= undefined ->
@@ -633,12 +686,10 @@ terminate(Reason, Name, Msg, Mod, StateName, StateData, Debug) ->
%% Priority shutdown should be considered as
%% shutdown by SASL
exit(shutdown);
- {process_limit, Limit} ->
- %% Priority shutdown should be considered as
- %% shutdown by SASL
- error_logger:error_msg("FSM limit reached (~p): ~p~n",
- [self(), Limit]),
- exit(shutdown);
+ {process_limit, _Limit} ->
+ exit(Reason);
+ {migrated, _Clone} ->
+ exit(normal);
_ ->
error_info(Mod, Reason, Name, Msg, StateName, StateData, Debug),
exit(Reason)
@@ -705,7 +756,12 @@ get_msg(Msg) -> Msg.
format_status(Opt, StatusData) ->
[PDict, SysState, Parent, Debug, [Name, StateName, StateData, Mod, _Time]] =
StatusData,
- Header = lists:concat(["Status for state machine ", Name]),
+ NameTag = if is_pid(Name) ->
+ pid_to_list(Name);
+ is_atom(Name) ->
+ Name
+ end,
+ Header = lists:concat(["Status for state machine ", NameTag]),
Log = sys:get_debug(log, Debug, []),
Specfic =
case erlang:function_exported(Mod, format_status, 2) of