From 6c298a7bfa332e5b7d153648d741740abc3bcdf8 Mon Sep 17 00:00:00 2001 From: Steve Vinoski Date: Wed, 19 Mar 2014 11:45:11 -0400 Subject: fix sys:get_state/1,2 and sys:replace_state/2,3 when sys suspended Add two new system callbacks Module:system_get_state/1 and Module:system_replace_state/2 to allow sys:get_state/1,2 and sys:replace_state/2,3 to operate correctly even if a process is sys suspended. Modify gen_server, gen_fsm, and gen_event to support the new callbacks. If a callback module does not export these functions, then by default the Misc value (the same as that passed as the final argument to sys:handle_system_msg/6, and returned as part of the return value of sys:get_status/1,2) is treated as the callback module's state. The previous behaviour of intercepting the system message and passing a tuple of size 2 as the last argument to sys:handle_system_msg/6 is no longer supported. Add tests to verify the correctness of sys:get_state/1,2 and sys:replace_state/2,3 when processes are sys suspended. Add two tests for modules that implement special processes, one that exports system_get_state/1 and system_replace_state/2 and one that doesn't. Much of the credit for this patch goes to James Fish, who reported the initial problem and implemented much of the fix. --- lib/stdlib/doc/src/sys.xml | 73 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 70 insertions(+), 3 deletions(-) (limited to 'lib/stdlib/doc/src/sys.xml') diff --git a/lib/stdlib/doc/src/sys.xml b/lib/stdlib/doc/src/sys.xml index ab8b380f49..a46fa1289f 100644 --- a/lib/stdlib/doc/src/sys.xml +++ b/lib/stdlib/doc/src/sys.xml @@ -246,6 +246,22 @@ {Module, Id, HandlerState}, where Module is the event handler's module name, Id is the handler's ID (which is the value false if it was registered without an ID), and HandlerState is the handler's state.

+

If the callback module exports a system_get_state/1 function, it will be called in the + target process to get its state. Its argument is the same as the Misc value returned by + get_status/1,2, and the system_get_state/1 + function is expected to extract the callback module's state from it. The system_get_state/1 + function must return {ok, State} where State is the callback module's state.

+

If the callback module does not export a system_get_state/1 function, get_state/1,2 + assumes the Misc value is the callback module's state and returns it directly instead.

+

If the callback module's system_get_state/1 function crashes or throws an exception, the + caller exits with error {callback_failed, {Module, system_get_state}, {Class, Reason}} where + Module is the name of the callback module and Class and Reason indicate + details of the exception.

+

The system_get_state/1 function is primarily useful for user-defined + behaviours and modules that implement OTP special + processes. The gen_server, gen_fsm, and gen_event OTP + behaviour modules export this function, and so callback modules for those behaviours + need not supply their own.

To obtain more information about a process, including its state, see get_status/1 and get_status/2.

@@ -289,6 +305,28 @@ function means that only the state of the particular event handler it was working on when it failed or crashed is unchanged; it can still succeed in changing the states of other event handlers registered in the same gen_event process.

+

If the callback module exports a system_replace_state/2 function, it will be called in the + target process to replace its state using StateFun. Its two arguments are StateFun + and Misc, where Misc is the same as the Misc value returned by + get_status/1,2. A system_replace_state/2 function + is expected to return {ok, NewState, NewMisc} where NewState is the callback module's + new state obtained by calling StateFun, and NewMisc is a possibly new value used to + replace the original Misc (required since Misc often contains the callback + module's state within it).

+

If the callback module does not export a system_replace_state/2 function, + replace_state/2,3 assumes the Misc value is the callback module's state, passes it + to StateFun and uses the return value as both the new state and as the new value of + Misc.

+

If the callback module's system_replace_state/2 function crashes or throws an exception, + the caller exits with error {callback_failed, {Module, system_replace_state}, {Class, Reason}} + where Module is the name of the callback module and Class and Reason indicate details + of the exception. If the callback module does not provide a system_replace_state/2 function and + StateFun crashes or throws an exception, the caller exits with error + {callback_failed, StateFun, {Class, Reason}}.

+

The system_replace_state/2 function is primarily useful for user-defined behaviours and + modules that implement OTP special processes. The + gen_server, gen_fsm, and gen_event OTP behaviour modules export this function, + and so callback modules for those behaviours need not supply their own.

@@ -322,7 +360,7 @@
Process Implementation Functions -

The following functions are used when implementing a +

The following functions are used when implementing a special process. This is an ordinary process which does not use a standard behaviour, but a process which understands the standard system messages.

@@ -375,8 +413,9 @@ process continues the execution, or Module:system_terminate(Reason, Parent, Debug, Misc) if the process should terminate. The Module must export - system_continue/3, system_terminate/4, and - system_code_change/4 (see below). + system_continue/3, system_terminate/4, + system_code_change/4, system_get_state/1 and + system_replace_state/2 (see below).

The Misc argument can be used to save internal data in a process, for example its state. It is sent to @@ -444,6 +483,34 @@ defined, the atom undefined is sent.

+ + Mod:system_get_state(Misc) -> {ok, State} + Called when the process should return its current state + + Misc = term() + State = term() + + +

This function is called from sys:handle_system_msg/6 when the process + should return a term that reflects its current state. State is the + value returned by sys:get_state/2.

+
+
+ + Mod:system_replace_state(StateFun, Misc) -> {ok, NState, NMisc} + Called when the process should replace its current state + + StateFun = fun((State :: term()) -> NState) + Misc = term() + NState = term() + NMisc = term() + + +

This function is called from sys:handle_system_msg/6 when the process + should replace its current state. NState is the value returned by + sys:replace_state/3.

+
+
-- cgit v1.2.3