Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:24
erlang
3011-Correct-the-type-spec-for-format_status-1....
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 3011-Correct-the-type-spec-for-format_status-1.patch of Package erlang
From 6e816a614be491ca7e8a4037e47860e3f6414c3d Mon Sep 17 00:00:00 2001 From: Raimo Niskanen <raimo@erlang.org> Date: Thu, 9 Jun 2022 18:22:20 +0200 Subject: [PATCH] Correct the type spec for format_status/1 The bad type spec in gen_statem, gen_server and gen_event stated that the return value of format_status/1 is exactly the input argument value, which is incorrect. To fix this, a type format_status() was needed in each module to be used both for the argument and the return value. This type is exported since it is essential for the format_status/1 function. Also, for gen_statem, a type event_content() :: term() was needed to facilitate documentation and to not lure any future code update into incorrectly using a type value EventContent multiple times in a bad way. --- lib/stdlib/doc/src/gen_event.xml | 75 ++++++++++++--------- lib/stdlib/doc/src/gen_server.xml | 76 +++++++++++++--------- lib/stdlib/doc/src/gen_statem.xml | 104 ++++++++++++++++++------------ lib/stdlib/src/gen_event.erl | 15 +++-- lib/stdlib/src/gen_server.erl | 17 +++-- lib/stdlib/src/gen_statem.erl | 73 +++++++++++---------- 6 files changed, 213 insertions(+), 147 deletions(-) diff --git a/lib/stdlib/doc/src/gen_event.xml b/lib/stdlib/doc/src/gen_event.xml index 8e947ebc0c..26a7f5646b 100644 --- a/lib/stdlib/doc/src/gen_event.xml +++ b/lib/stdlib/doc/src/gen_event.xml @@ -202,6 +202,31 @@ gen_event:stop -----> Module:terminate/2 </desc> </datatype> + <datatype> + <name name="format_status"/> + <desc> + <p> + A map that describes the <c>gen_event</c> process status. + The keys are: + </p> + <taglist> + <tag><c>state</c></tag> + <item>The internal state of the event handler.</item> + <tag><c>message</c></tag> + <item>The message that caused the event handler to terminate.</item> + <tag><c>reason</c></tag> + <item>The reason that caused the event handler to terminate.</item> + <tag><c>log</c></tag> + <item> + The <seemfa marker="sys#log/2">sys log</seemfa> of the server. + </item> + </taglist> + <p> + New associations may be added into the status map + without prior notice. + </p> + </desc> + </datatype> </datatypes> <funcs> @@ -1243,16 +1268,8 @@ gen_event:stop -----> Module:terminate/2 <fsummary>Optional function for providing a term describing the current event handler state.</fsummary> <type> - <v>Status = #{ state => State,</v> - <v> - message => Message,</v> - <v> - reason => Reason,</v> - <v> - log => Log }</v> - <v>NewStatus = Status</v> - <v>State = Message = Reason = term()</v> - <v>Log = [<seetype marker="sys#system_event">sys:system_event()</seetype>]</v> + <v>Status = <seetype marker="#format_status">format_status()</seetype></v> + <v>NewStatus = <seetype marker="#format_status">format_status()</seetype></v> </type> <desc> <note> @@ -1274,27 +1291,25 @@ gen_event:stop -----> Module:terminate/2 <item>The event handler terminates abnormally and <c>gen_event</c> logs an error.</item> </list> - <p>This callback is to be used to limit the status of the event handler before - returned by <seemfa marker="sys#get_status/1"><c>sys:get_status/1,2</c></seemfa> or - sent to <seeerl marker="kernel:logger"><c>logger</c></seeerl>. The status - of the event handler is passed as a map with the following associations: + <p> + This callback is used to limit the status of the event handler + returned by + <seemfa marker="sys#get_status/1"><c>sys:get_status/1,2</c></seemfa> + or sent to <seeerl marker="kernel:logger"><c>logger</c></seeerl>. + </p> + <p> + The callback gets a map <c>Status</c> + describing the current status and shall return a map + <c>NewStatus</c> with the same keys, + but it may transform some values. + </p> + <p> + Two possible use cases for this callback is to + remove sensitive information from the state + to prevent it from being printed in log files, + or to compact large irrelevant status items + that would only clutter the logs. </p> - <taglist> - <tag><c>state => term()</c></tag> - <item>The internal state of the event handler.</item> - <tag><c>message => term()</c></tag> - <item>The message that caused the event handler to terminate.</item> - <tag><c>reason => term()</c></tag> - <item>The reason that caused the event handler to terminate.</item> - <tag><c>log => [</c><seetype marker="sys#system_event"><c>sys:system_event/0</c></seetype><c>]</c></tag> - <item>The <seemfa marker="sys#log/2">sys log</seemfa> of the server.</item> - </taglist> - <p>New associations may be added into the status map without prior notice.</p> - <p>The function is to return <c>NewStatus</c>, a map containing the same - associations as the input map.</p> - <p>Two possible use cases for this callback is to either remove - sensitive information from the state so that it not printed in log files, - or to remove large irrelevant terms of state that clutter the logs.</p> <code type="erl"><![CDATA[ format_status(Status) -> maps:map( diff --git a/lib/stdlib/doc/src/gen_server.xml b/lib/stdlib/doc/src/gen_server.xml index cc41e0c369..4948418b3d 100644 --- a/lib/stdlib/doc/src/gen_server.xml +++ b/lib/stdlib/doc/src/gen_server.xml @@ -473,6 +473,32 @@ gen_server:abcast -----> Module:handle_cast/2 </taglist> </desc> </datatype> + + <datatype> + <name name="format_status"/> + <desc> + <p> + A map that describes the <c>gen_server</c> status. + The keys are: + </p> + <taglist> + <tag><c>state</c></tag> + <item>The internal state of the <c>gen_server</c> process.</item> + <tag><c>message</c></tag> + <item>The message that caused the server to terminate.</item> + <tag><c>reason</c></tag> + <item>The reason that caused the server to terminate.</item> + <tag><c>log</c></tag> + <item> + The <seemfa marker="sys#log/2">sys log</seemfa> of the server. + </item> + </taglist> + <p> + New associations may be added to the status map + without prior notice. + </p> + </desc> + </datatype> </datatypes> @@ -1513,16 +1539,8 @@ gen_server:abcast -----> Module:handle_cast/2 <fsummary>Optional function for providing a term describing the current <c>gen_server</c> status.</fsummary> <type> - <v>Status = #{ state => State,</v> - <v> - message => Message,</v> - <v> - reason => Reason,</v> - <v> - log => Log }</v> - <v>NewStatus = Status</v> - <v>State = Message = Reason = term()</v> - <v>Log = [<seetype marker="sys#system_event">sys:system_event()</seetype>]</v> + <v>Status = <seetype marker="#format_status">format_status()</seetype></v> + <v>NewStatus = <seetype marker="#format_status">format_status()</seetype></v> </type> <desc> <note> @@ -1545,27 +1563,25 @@ gen_server:abcast -----> Module:handle_cast/2 <p>The <c>gen_server</c> process terminates abnormally and logs an error.</p> </item> </list> - <p>This callback is to be used to limit the status of the process before - returned by <seemfa marker="sys#get_status/1"><c>sys:get_status/1,2</c></seemfa> or - sent to <seeerl marker="kernel:logger"><c>logger</c></seeerl>. The status - of the server is passed as a map with the following associations: + <p> + This callback is used to limit the status of the process + returned by + <seemfa marker="sys#get_status/1"><c>sys:get_status/1,2</c></seemfa> + or sent to <seeerl marker="kernel:logger"><c>logger</c></seeerl>. + </p> + <p> + The callback gets a map <c>Status</c> + describing the current status and shall return a map + <c>NewStatus</c> with the same keys, + but it may transform some values. + </p> + <p> + Two possible use cases for this callback is to + remove sensitive information from the state + to prevent it from being printed in log files, + or to compact large irrelevant status items + that would only clutter the logs. </p> - <taglist> - <tag><c>state => term()</c></tag> - <item>The internal state of the <c>gen_server</c> process.</item> - <tag><c>message => term()</c></tag> - <item>The message that caused the server to terminate.</item> - <tag><c>reason => term()</c></tag> - <item>The reason that caused the server to terminate.</item> - <tag><c>log => [</c><seetype marker="sys#system_event"><c>sys:system_event/0</c></seetype><c>]</c></tag> - <item>The <seemfa marker="sys#log/2">sys log</seemfa> of the server.</item> - </taglist> - <p>New associations may be added into the status map without prior notice.</p> - <p>The function is to return <c>NewStatus</c>, a map containing the same - associations as the input map.</p> - <p>Two possible use cases for this callback is to either remove - sensitive information from the state so that it not printed in log files, - or to remove large irrelevant terms of state that do clutter the logs.</p> <p>Example:</p> <code type="erl"><![CDATA[ format_status(Status) -> diff --git a/lib/stdlib/doc/src/gen_statem.xml b/lib/stdlib/doc/src/gen_statem.xml index 398b32ae05..9dd1c6f270 100644 --- a/lib/stdlib/doc/src/gen_statem.xml +++ b/lib/stdlib/doc/src/gen_statem.xml @@ -733,6 +733,19 @@ handle_event(_, _, State, Data) -> </p> </desc> </datatype> + <datatype> + <name name="event_content"/> + <desc> + <p> + Any event's content can be any term. + </p> + <p> + See <seetype marker="#event_type"><c>event_type</c></seetype> + that describes the origins of the different event types, + which is also where the event content comes from. + </p> + </desc> + </datatype> <datatype> <name name="callback_mode_result"/> <desc> @@ -1685,6 +1698,45 @@ handle_event(_, _, State, Data) -> </taglist> </desc> </datatype> + + <datatype> + <name name="format_status"/> + <desc> + <p> + A map that describes the <c>gen_statem</c> status. + The keys are: + </p> + <taglist> + <tag><c>state</c></tag> + <item>The current state of the <c>gen_statem</c> process.</item> + <tag><c>data</c></tag> + <item>The state data of the the <c>gen_statem</c> process.</item> + <tag><c>reason</c></tag> + <item>The reason that caused the state machine to terminate.</item> + <tag><c>queue</c></tag> + <item>The event queue of the <c>gen_statem</c> process.</item> + <tag><c>postponed</c></tag> + <item> + The <seetype marker="#postpone">postponed</seetype> + events queue of the <c>gen_statem</c> process. + </item> + <tag><c>timeouts</c></tag> + <item> + The active + <seetype marker="#timeout_action">time-outs</seetype> + of the <c>gen_statem</c> process. + </item> + <tag><c>log</c></tag> + <item> + The <seemfa marker="sys#log/2">sys log</seemfa> of the server. + </item> + </taglist> + <p> + New associations may be added to the status map + without prior notice. + </p> + </desc> + </datatype> </datatypes> <funcs> @@ -2918,25 +2970,8 @@ init(Args) -> erlang:error(not_implemented, [Args]).</pre> <fsummary>Optional function for providing a term describing the current <c>gen_statem</c> status.</fsummary> <type> - <v>Status = #{ state => <seetype marker="#state">state()</seetype>,</v> - <v> - reason => term(),</v> - <v> - data => <seetype marker="#data">data()</seetype>,</v> - <v> - queue => Queue,</v> - <v> - postponed => Postponed,</v> - <v> - timeouts => Timeouts,</v> - <v> - log => Log }</v> - <v>NewStatus = Status</v> - <v>Queue = Postponed = [{EventType,EventContent}]</v> - <v>EventType = <seetype marker="#event_type">event_type()</seetype></v> - <v>Timeouts = [{<seetype marker="#timeout_event_type">timeout_event_type()</seetype>,EventContent}]</v> - <v>EventContent = term()</v> - <v>Log = [<seetype marker="sys#system_event">sys:system_event()</seetype>]</v> + <v>Status = <seetype marker="#format_status">format_status()</seetype></v> + <v>NewStatus = <seetype marker="#format_status">format_status()</seetype></v> </type> <desc> <note> @@ -2971,31 +3006,18 @@ init(Args) -> erlang:error(not_implemented, [Args]).</pre> callback module wishing to change the <seemfa marker="sys#get_status/1"><c>sys:get_status/1,2</c></seemfa> return value and how - its status appears in termination error logs exports an - instance of <c>format_status/1</c>, which returns a map - describing the current status of the <c>gen_statem</c>. + its status appears in termination error logs exports + an instance of <c>format_status/1</c>, + which will get a map <c>Status</c> that describes + the current states of the <c>gen_statem</c>, + and shall return a map <c>NewStatus</c> + containing the same keys as the input map, + but it may transform some values. </p> - <taglist> - <tag><c>state => </c><seetype marker="#state"><c>state()</c></seetype></tag> - <item>The current state of the <c>gen_statem</c> process.</item> - <tag><c>data => </c><seetype marker="#data"><c>data()</c></seetype></tag> - <item>The state data of the the <c>gen_statem</c> process.</item> - <tag><c>reason => term()</c></tag> - <item>The reason that caused the state machine to terminate.</item> - <tag><c>queue => [{</c><seetype marker="#event_type"><c>event_type()</c></seetype><c>,term()}]</c></tag> - <item>The event queue of the <c>gen_statem</c> process.</item> - <tag><c>postponed => [{</c><seetype marker="#event_type"><c>event_type()</c></seetype><c>,term()}]</c></tag> - <item>The <seetype marker="#postpone">postponed</seetype> events queue of the <c>gen_statem</c> process.</item> - <tag><c>log => [</c><seetype marker="sys#system_event"><c>sys:system_event/0</c></seetype><c>]</c></tag> - <item>The <seemfa marker="sys#log/2">sys log</seemfa> of the server.</item> - </taglist> - <p>New associations may be added into the status map without prior notice.</p> - <p>The function is to return <c>NewStatus</c>, a map containing the same - associations as the input map.</p> - <p> + <p> One use case for this function is to return compact alternative state representations to avoid having large state terms - printed in log files. Another use is to hide sensitive data from + printed in log files. Another is to hide sensitive data from being written to the error log. </p> <p>Example:</p> diff --git a/lib/stdlib/src/gen_event.erl b/lib/stdlib/src/gen_event.erl index 3f5737f304..20d9910374 100644 --- a/lib/stdlib/src/gen_event.erl +++ b/lib/stdlib/src/gen_event.erl @@ -62,7 +62,8 @@ -export([format_log/1, format_log/2]). -export_type([handler/0, handler_args/0, add_handler_ret/0, - del_handler_ret/0, request_id/0, request_id_collection/0]). + del_handler_ret/0, request_id/0, request_id_collection/0, + format_status/0]). -record(handler, {module :: atom(), id = false, @@ -122,12 +123,14 @@ PDict :: [{Key :: term(), Value :: term()}], State :: term(), Status :: term(). +-type format_status() :: + #{ state => term(), + message => term(), + reason => term(), + log => [sys:system_event()] }. -callback format_status(Status) -> NewStatus when - Status :: #{ state => term(), - message => term(), - reason => term(), - log => [sys:system_event()] }, - NewStatus :: Status. + Status :: format_status(), + NewStatus :: format_status(). -optional_callbacks( [handle_info/2, terminate/2, code_change/3, format_status/1, format_status/2]). diff --git a/lib/stdlib/src/gen_server.erl b/lib/stdlib/src/gen_server.erl index 14858e3eb5..af5e04f78a 100644 --- a/lib/stdlib/src/gen_server.erl +++ b/lib/stdlib/src/gen_server.erl @@ -127,7 +127,8 @@ [from/0, reply_tag/0, request_id/0, - request_id_collection/0]). + request_id_collection/0, + format_status/0]). -export_type( [server_name/0, @@ -180,18 +181,20 @@ -callback code_change(OldVsn :: (term() | {down, term()}), State :: term(), Extra :: term()) -> {ok, NewState :: term()} | {error, Reason :: term()}. --callback format_status(Status) -> NewStatus when - Status :: #{ state => term(), - message => term(), - reason => term(), - log => [sys:system_event()] }, - NewStatus :: Status. -callback format_status(Opt, StatusData) -> Status when Opt :: 'normal' | 'terminate', StatusData :: [PDict | State], PDict :: [{Key :: term(), Value :: term()}], State :: term(), Status :: term(). +-type format_status() :: + #{ state => term(), + message => term(), + reason => term(), + log => [sys:system_event()] }. +-callback format_status(Status) -> NewStatus when + Status :: format_status(), + NewStatus :: format_status(). -optional_callbacks( [handle_info/2, handle_continue/2, terminate/2, code_change/3, diff --git a/lib/stdlib/src/gen_statem.erl b/lib/stdlib/src/gen_statem.erl index f82965d925..3d9bae547e 100644 --- a/lib/stdlib/src/gen_statem.erl +++ b/lib/stdlib/src/gen_statem.erl @@ -77,7 +77,8 @@ enter_action/0, action/0, request_id/0, - request_id_collection/0 + request_id_collection/0, + format_status/0 ]). %% Old types, not advertised -export_type( @@ -119,6 +120,8 @@ -type timeout_event_type() :: 'timeout' | {'timeout', Name :: term()} | 'state_timeout'. +-type event_content() :: term(). + -type callback_mode_result() :: callback_mode() | [callback_mode() | state_enter()]. -type callback_mode() :: 'state_functions' | 'handle_event_function'. @@ -170,7 +173,7 @@ %% action() list is the first to be delivered. {'next_event', % Insert event as the next to handle EventType :: event_type(), - EventContent :: term()} | + EventContent :: event_content()} | {'change_callback_module', NewModule :: module()} | {'push_callback_module', NewModule :: module()} | 'pop_callback_module' | @@ -183,24 +186,24 @@ -type timeout_action() :: (Time :: event_timeout()) | % {timeout,Time,Time} {'timeout', % Set the event_timeout option - Time :: event_timeout(), EventContent :: term()} | + Time :: event_timeout(), EventContent :: event_content()} | {'timeout', % Set the event_timeout option Time :: event_timeout(), - EventContent :: term(), + EventContent :: event_content(), Options :: (timeout_option() | [timeout_option()])} | %% {{'timeout', Name :: term()}, % Set the generic_timeout option - Time :: generic_timeout(), EventContent :: term()} | + Time :: generic_timeout(), EventContent :: event_content()} | {{'timeout', Name :: term()}, % Set the generic_timeout option Time :: generic_timeout(), - EventContent :: term(), + EventContent :: event_content(), Options :: (timeout_option() | [timeout_option()])} | %% {'state_timeout', % Set the state_timeout option - Time :: state_timeout(), EventContent :: term()} | + Time :: state_timeout(), EventContent :: event_content()} | {'state_timeout', % Set the state_timeout option Time :: state_timeout(), - EventContent :: term(), + EventContent :: event_content(), Options :: (timeout_option() | [timeout_option()])} | timeout_cancel_action() | timeout_update_action(). @@ -209,9 +212,10 @@ {{'timeout', Name :: term()}, 'cancel'} | {'state_timeout', 'cancel'}. -type timeout_update_action() :: - {'timeout', 'update', EventContent :: term()} | - {{'timeout', Name :: term()}, 'update', EventContent :: term()} | - {'state_timeout', 'update', EventContent :: term()}. + {'timeout', 'update', EventContent :: event_content()} | + {{'timeout', Name :: term()}, + 'update', EventContent :: event_content()} | + {'state_timeout', 'update', EventContent :: event_content()}. -type reply_action() :: {'reply', % Reply to a caller From :: from(), Reply :: term()}. @@ -317,11 +321,11 @@ -callback 'StateName'( 'enter', OldStateName :: state_name(), - Data :: data()) -> + data()) -> state_enter_result('state_name'); (event_type(), - EventContent :: term(), - Data :: data()) -> + event_content(), + data()) -> event_handler_result(state_name()). %% %% State callback for all states @@ -329,21 +333,21 @@ -callback handle_event( 'enter', OldState :: state(), - State, % Current state - Data :: data()) -> - state_enter_result(State); + CurrentState, + data()) -> + state_enter_result(CurrentState); (event_type(), - EventContent :: term(), - State :: state(), % Current state - Data :: data()) -> - event_handler_result(state()). + event_content(), + CurrentState :: state(), + data()) -> + event_handler_result(state()). % New state %% Clean up before the server terminates. -callback terminate( Reason :: 'normal' | 'shutdown' | {'shutdown', term()} | term(), - State :: state(), - Data :: data()) -> + CurrentState :: state(), + data()) -> any(). %% Note that the new code can expect to get an OldState from @@ -371,17 +375,20 @@ Status :: term() when StatusOption :: 'normal' | 'terminate'. +-type format_status() :: + #{ state => state(), + data => data(), + reason => term(), + queue => [{event_type(), event_content()}], + postponed => [{event_type(), event_content()}], + timeouts => [{timeout_event_type(), event_content()}], + log => [sys:system_event()] }. + %% Format the callback module status in some sensible that is %% often condensed way. -callback format_status(Status) -> NewStatus when - Status :: #{ state => state(), - data => data(), - reason => term(), - queue => [{event_type(), term()}], - postponed => [{event_type(), term()}], - timeouts => [{timeout_event_type(), term()}], - log => [sys:system_event()] }, - NewStatus :: Status. + Status :: format_status(), + NewStatus :: format_status(). -optional_callbacks( [format_status/1, % Has got a default implementation @@ -482,7 +489,7 @@ timeout_event_type(Type) -> -record(state, {state_data = {undefined,undefined} :: {State :: term(),Data :: term()}, - postponed = [] :: [{event_type(),term()}], + postponed = [] :: [{event_type(),event_content()}], timers = #{t0q => []} :: #{ %% Timeout 0 Queue. @@ -493,7 +500,7 @@ timeout_event_type(Type) -> TimeoutType :: timeout_event_type() => {TimerRef :: reference() | 0, - TimeoutMsg :: term()}}, + TimeoutMsg :: event_content()}}, hibernate = false :: boolean() }). -- 2.35.3
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor