<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html xmlns:fn="http://www.w3.org/2005/02/xpath-functions"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <link rel="stylesheet" href="../otp_doc.css" type="text/css"> <title>Erlang -- Sys and Proc_Lib</title> </head> <body bgcolor="white" text="#000000" link="#0000ff" vlink="#ff00ff" alink="#ff0000"><div id="container"> <script id="js" type="text/javascript" language="JavaScript" src="../js/flipmenu/flipmenu.js"></script><script id="js2" type="text/javascript" src="../js/erlresolvelinks.js"></script><script language="JavaScript" type="text/javascript"> <!-- function getWinHeight() { var myHeight = 0; if( typeof( window.innerHeight ) == 'number' ) { //Non-IE myHeight = window.innerHeight; } else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) { //IE 6+ in 'standards compliant mode' myHeight = document.documentElement.clientHeight; } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) { //IE 4 compatible myHeight = document.body.clientHeight; } return myHeight; } function setscrollpos() { var objf=document.getElementById('loadscrollpos'); document.getElementById("leftnav").scrollTop = objf.offsetTop - getWinHeight()/2; } function addEvent(obj, evType, fn){ if (obj.addEventListener){ obj.addEventListener(evType, fn, true); return true; } else if (obj.attachEvent){ var r = obj.attachEvent("on"+evType, fn); return r; } else { return false; } } addEvent(window, 'load', setscrollpos); //--></script><div id="leftnav"><div class="innertube"> <img alt="Erlang logo" src="../erlang-logo.png"><br><small><a href="users_guide.html">User's Guide</a><br><a href="../pdf/otp-system-documentation-5.9.3.1.pdf">PDF</a><br><a href="../index.html">Top</a></small><p><strong>OTP Design Principles</strong><br><strong>User's Guide</strong><br><small>Version 5.9.3.1</small></p> <br><a href="javascript:openAllFlips()">Expand All</a><br><a href="javascript:closeAllFlips()">Contract All</a><p><small><strong>Chapters</strong></small></p> <ul class="flipMenu" imagepath="../js/flipmenu"> <li id="no" title="Overview" expanded="false">Overview<ul> <li><a href="des_princ.html"> Top of chapter </a></li> <li title="Supervision Trees"><a href="des_princ.html#id65609">Supervision Trees</a></li> <li title="Behaviours"><a href="des_princ.html#id59741">Behaviours</a></li> <li title="Applications"><a href="des_princ.html#id66345">Applications</a></li> <li title="Releases"><a href="des_princ.html#id61095">Releases</a></li> <li title="Release Handling"><a href="des_princ.html#id60860">Release Handling</a></li> </ul> </li> <li id="no" title="Gen_Server Behaviour" expanded="false">Gen_Server Behaviour<ul> <li><a href="gen_server_concepts.html"> Top of chapter </a></li> <li title="Client-Server Principles"><a href="gen_server_concepts.html#id64192">Client-Server Principles</a></li> <li title="Example"><a href="gen_server_concepts.html#id61515">Example</a></li> <li title="Starting a Gen_Server"><a href="gen_server_concepts.html#id67798">Starting a Gen_Server</a></li> <li title="Synchronous Requests - Call"><a href="gen_server_concepts.html#id66815">Synchronous Requests - Call</a></li> <li title="Asynchronous Requests - Cast"><a href="gen_server_concepts.html#id62843">Asynchronous Requests - Cast</a></li> <li title="Stopping"><a href="gen_server_concepts.html#id67345">Stopping</a></li> <li title="Handling Other Messages"><a href="gen_server_concepts.html#id67435">Handling Other Messages</a></li> </ul> </li> <li id="no" title="Gen_Fsm Behaviour" expanded="false">Gen_Fsm Behaviour<ul> <li><a href="fsm.html"> Top of chapter </a></li> <li title="Finite State Machines"><a href="fsm.html#id68991">Finite State Machines</a></li> <li title="Example"><a href="fsm.html#id69046">Example</a></li> <li title="Starting a Gen_Fsm"><a href="fsm.html#id69093">Starting a Gen_Fsm</a></li> <li title="Notifying About Events"><a href="fsm.html#id69273">Notifying About Events</a></li> <li title="Timeouts"><a href="fsm.html#id69352">Timeouts</a></li> <li title="All State Events"><a href="fsm.html#id69391">All State Events</a></li> <li title="Stopping"><a href="fsm.html#id69423">Stopping</a></li> <li title="Handling Other Messages"><a href="fsm.html#id69514">Handling Other Messages</a></li> </ul> </li> <li id="no" title="Gen_Event Behaviour" expanded="false">Gen_Event Behaviour<ul> <li><a href="events.html"> Top of chapter </a></li> <li title="Event Handling Principles"><a href="events.html#id69613">Event Handling Principles</a></li> <li title="Example"><a href="events.html#id69665">Example</a></li> <li title="Starting an Event Manager"><a href="events.html#id69706">Starting an Event Manager</a></li> <li title="Adding an Event Handler"><a href="events.html#id70832">Adding an Event Handler</a></li> <li title="Notifying About Events"><a href="events.html#id70916">Notifying About Events</a></li> <li title="Deleting an Event Handler"><a href="events.html#id70987">Deleting an Event Handler</a></li> <li title="Stopping"><a href="events.html#id71062">Stopping</a></li> <li title="Handling Other Messages"><a href="events.html#id71116">Handling Other Messages</a></li> </ul> </li> <li id="no" title="Supervisor Behaviour" expanded="false">Supervisor Behaviour<ul> <li><a href="sup_princ.html"> Top of chapter </a></li> <li title="Supervision Principles"><a href="sup_princ.html#id71210">Supervision Principles</a></li> <li title="Example"><a href="sup_princ.html#id71235">Example</a></li> <li title="Restart Strategy"><a href="sup_princ.html#id71306">Restart Strategy</a></li> <li title="Maximum Restart Frequency"><a href="sup_princ.html#id71384">Maximum Restart Frequency</a></li> <li title="Child Specification"><a href="sup_princ.html#id71906">Child Specification</a></li> <li title="Starting a Supervisor"><a href="sup_princ.html#id72235">Starting a Supervisor</a></li> <li title="Adding a Child Process"><a href="sup_princ.html#id72349">Adding a Child Process</a></li> <li title="Stopping a Child Process"><a href="sup_princ.html#id72393">Stopping a Child Process</a></li> <li title="Simple-One-For-One Supervisors"><a href="sup_princ.html#id72443">Simple-One-For-One Supervisors</a></li> <li title="Stopping"><a href="sup_princ.html#id72567">Stopping</a></li> </ul> </li> <li id="loadscrollpos" title="Sys and Proc_Lib" expanded="true">Sys and Proc_Lib<ul> <li><a href="spec_proc.html"> Top of chapter </a></li> <li title="Simple Debugging"><a href="spec_proc.html#id72665">Simple Debugging</a></li> <li title="Special Processes"><a href="spec_proc.html#id72749">Special Processes</a></li> <li title="User-Defined Behaviours"><a href="spec_proc.html#id73359">User-Defined Behaviours</a></li> </ul> </li> <li id="no" title="Applications" expanded="false">Applications<ul> <li><a href="applications.html"> Top of chapter </a></li> <li title="Application Concept"><a href="applications.html#id73539">Application Concept</a></li> <li title="Application Callback Module"><a href="applications.html#id73606">Application Callback Module</a></li> <li title="Application Resource File"><a href="applications.html#id73720">Application Resource File</a></li> <li title="Directory Structure"><a href="applications.html#id73969">Directory Structure</a></li> <li title="Application Controller"><a href="applications.html#id74095">Application Controller</a></li> <li title="Loading and Unloading Applications"><a href="applications.html#id74128">Loading and Unloading Applications</a></li> <li title="Starting and Stopping Applications"><a href="applications.html#id74190">Starting and Stopping Applications</a></li> <li title="Configuring an Application"><a href="applications.html#id74278">Configuring an Application</a></li> <li title="Application Start Types"><a href="applications.html#id74477">Application Start Types</a></li> </ul> </li> <li id="no" title="Included Applications" expanded="false">Included Applications<ul> <li><a href="included_applications.html"> Top of chapter </a></li> <li title="Definition"><a href="included_applications.html#id74617">Definition</a></li> <li title="Specifying Included Applications"><a href="included_applications.html#id74682">Specifying Included Applications</a></li> <li title="Synchronizing Processes During Startup"><a href="included_applications.html#id74708">Synchronizing Processes During Startup</a></li> </ul> </li> <li id="no" title="Distributed Applications" expanded="false">Distributed Applications<ul> <li><a href="distributed_applications.html"> Top of chapter </a></li> <li title="Definition"><a href="distributed_applications.html#id74921">Definition</a></li> <li title="Specifying Distributed Applications"><a href="distributed_applications.html#id74957">Specifying Distributed Applications</a></li> <li title="Starting and Stopping Distributed Applications"><a href="distributed_applications.html#id75164">Starting and Stopping Distributed Applications</a></li> <li title="Failover"><a href="distributed_applications.html#id75266">Failover</a></li> <li title="Takeover"><a href="distributed_applications.html#id75408">Takeover</a></li> </ul> </li> <li id="no" title="Releases" expanded="false">Releases<ul> <li><a href="release_structure.html"> Top of chapter </a></li> <li title="Release Concept"><a href="release_structure.html#id75603">Release Concept</a></li> <li title="Release Resource File"><a href="release_structure.html#id75656">Release Resource File</a></li> <li title="Generating Boot Scripts"><a href="release_structure.html#id75803">Generating Boot Scripts</a></li> <li title="Creating a Release Package"><a href="release_structure.html#id75897">Creating a Release Package</a></li> <li title="Directory Structure"><a href="release_structure.html#id76046">Directory Structure</a></li> </ul> </li> <li id="no" title="Release Handling" expanded="false">Release Handling<ul> <li><a href="release_handling.html"> Top of chapter </a></li> <li title="Release Handling Principles"><a href="release_handling.html#id76299">Release Handling Principles</a></li> <li title="Requirements"><a href="release_handling.html#id76543">Requirements</a></li> <li title="Distributed Systems"><a href="release_handling.html#id76636">Distributed Systems</a></li> <li title="Release Handling Instructions"><a href="release_handling.html#id76663">Release Handling Instructions</a></li> <li title="Application Upgrade File"><a href="release_handling.html#id77177">Application Upgrade File</a></li> <li title="Release Upgrade File"><a href="release_handling.html#id77359">Release Upgrade File</a></li> <li title="Installing a Release"><a href="release_handling.html#id77515">Installing a Release</a></li> <li title="Updating Application Specifications"><a href="release_handling.html#id77986">Updating Application Specifications</a></li> </ul> </li> <li id="no" title="Appup Cookbook" expanded="false">Appup Cookbook<ul> <li><a href="appup_cookbook.html"> Top of chapter </a></li> <li title="Changing a Functional Module"><a href="appup_cookbook.html#id78170">Changing a Functional Module</a></li> <li title="Changing a Residence Module"><a href="appup_cookbook.html#id78193">Changing a Residence Module</a></li> <li title="Changing a Callback Module"><a href="appup_cookbook.html#id78232">Changing a Callback Module</a></li> <li title="Changing Internal State"><a href="appup_cookbook.html#id78283">Changing Internal State</a></li> <li title="Module Dependencies"><a href="appup_cookbook.html#id78417">Module Dependencies</a></li> <li title="Changing Code For a Special Process"><a href="appup_cookbook.html#id78588">Changing Code For a Special Process</a></li> <li title="Changing a Supervisor"><a href="appup_cookbook.html#id78755">Changing a Supervisor</a></li> <li title="Adding or Deleting a Module"><a href="appup_cookbook.html#id79000">Adding or Deleting a Module</a></li> <li title="Starting or Terminating a Process"><a href="appup_cookbook.html#id79026">Starting or Terminating a Process</a></li> <li title="Adding or Removing an Application"><a href="appup_cookbook.html#id79044">Adding or Removing an Application</a></li> <li title="Restarting an Application"><a href="appup_cookbook.html#id79075">Restarting an Application</a></li> <li title="Changing an Application Specification"><a href="appup_cookbook.html#id79117">Changing an Application Specification</a></li> <li title="Changing Application Configuration"><a href="appup_cookbook.html#id79141">Changing Application Configuration</a></li> <li title="Changing Included Applications"><a href="appup_cookbook.html#id79174">Changing Included Applications</a></li> <li title="Changing Non-Erlang Code"><a href="appup_cookbook.html#id79414">Changing Non-Erlang Code</a></li> <li title="Emulator Restart and Upgrade"><a href="appup_cookbook.html#id79499">Emulator Restart and Upgrade</a></li> <li title="Emulator Upgrade from pre OTP R15"><a href="appup_cookbook.html#id79575">Emulator Upgrade from pre OTP R15</a></li> </ul> </li> </ul> </div></div> <div id="content"> <div class="innertube"> <h1>6 Sys and Proc_Lib</h1> <p>The module <span class="code">sys</span> contains functions for simple debugging of processes implemented using behaviours.</p> <p>There are also functions that, together with functions in the module <span class="code">proc_lib</span>, can be used to implement a <strong>special process</strong>, a process which comply to the OTP design principles without making use of a standard behaviour. They can also be used to implement user defined (non-standard) behaviours.</p> <p>Both <span class="code">sys</span> and <span class="code">proc_lib</span> belong to the STDLIB application.</p> <h3><a name="id72665">6.1 Simple Debugging</a></h3> <p>The module <span class="code">sys</span> contains some functions for simple debugging of processes implemented using behaviours. We use the <span class="code">code_lock</span> example from the <span class="bold_code"><a href="fsm.html#ex">gen_event</a></span> chapter to illustrate this:</p> <div class="example"><pre> % <span class="bold_code">erl</span> Erlang (BEAM) emulator version 5.2.3.6 [hipe] [threads:0] Eshell V5.2.3.6 (abort with ^G) 1> <span class="bold_code">code_lock:start_link([1,2,3,4]).</span> {ok,<0.32.0>} 2> <span class="bold_code">sys:statistics(code_lock, true).</span> ok 3> <span class="bold_code">sys:trace(code_lock, true).</span> ok 4> <span class="bold_code">code_lock:button(4).</span> *DBG* code_lock got event {button,4} in state closed ok *DBG* code_lock switched to state closed 5> <span class="bold_code">code_lock:button(3).</span> *DBG* code_lock got event {button,3} in state closed ok *DBG* code_lock switched to state closed 6> <span class="bold_code">code_lock:button(2).</span> *DBG* code_lock got event {button,2} in state closed ok *DBG* code_lock switched to state closed 7> <span class="bold_code">code_lock:button(1).</span> *DBG* code_lock got event {button,1} in state closed ok OPEN DOOR *DBG* code_lock switched to state open *DBG* code_lock got event timeout in state open CLOSE DOOR *DBG* code_lock switched to state closed 8> <span class="bold_code">sys:statistics(code_lock, get).</span> {ok,[{start_time,{{2003,6,12},{14,11,40}}}, {current_time,{{2003,6,12},{14,12,14}}}, {reductions,333}, {messages_in,5}, {messages_out,0}]} 9> <span class="bold_code">sys:statistics(code_lock, false).</span> ok 10> <span class="bold_code">sys:trace(code_lock, false).</span> ok 11> <span class="bold_code">sys:get_status(code_lock).</span> {status,<0.32.0>, {module,gen_fsm}, [[{'$ancestors',[<0.30.0>]}, {'$initial_call',{gen,init_it, [gen_fsm,<0.30.0>,<0.30.0>, {local,code_lock}, code_lock, [1,2,3,4], []]}}], running,<0.30.0>,[], [code_lock,closed,{[],[1,2,3,4]},code_lock,infinity]]}</pre></div> <h3><a name="id72749">6.2 Special Processes</a></h3> <p>This section describes how to write a process which comply to the OTP design principles, without making use of a standard behaviour. Such a process should:</p> <ul> <li>be started in a way that makes the process fit into a supervision tree,</li> <li>support the <span class="code">sys</span> <span class="bold_code"><a href="#debug">debug facilities</a></span>, and</li> <li>take care of <span class="bold_code"><a href="#msg">system messages</a></span>.</li> </ul> <p>System messages are messages with special meaning, used in the supervision tree. Typical system messages are requests for trace output, and requests to suspend or resume process execution (used during release handling). Processes implemented using standard behaviours automatically understand these messages.</p> <h4>Example</h4> <p>The simple server from the <span class="bold_code"><a href="des_princ.html#ch1">Overview</a></span> chapter, implemented using <span class="code">sys</span> and <span class="code">proc_lib</span> so it fits into a supervision tree:</p> <a name="ex"></a> <div class="example"><pre> -module(ch4). -export([start_link/0]). -export([alloc/0, free/1]). -export([init/1]). -export([system_continue/3, system_terminate/4, write_debug/3]). start_link() -> proc_lib:start_link(ch4, init, [self()]). alloc() -> ch4 ! {self(), alloc}, receive {ch4, Res} -> Res end. free(Ch) -> ch4 ! {free, Ch}, ok. init(Parent) -> register(ch4, self()), Chs = channels(), Deb = sys:debug_options([]), proc_lib:init_ack(Parent, {ok, self()}), loop(Chs, Parent, Deb). loop(Chs, Parent, Deb) -> receive {From, alloc} -> Deb2 = sys:handle_debug(Deb, {ch4, write_debug}, ch4, {in, alloc, From}), {Ch, Chs2} = alloc(Chs), From ! {ch4, Ch}, Deb3 = sys:handle_debug(Deb2, {ch4, write_debug}, ch4, {out, {ch4, Ch}, From}), loop(Chs2, Parent, Deb3); {free, Ch} -> Deb2 = sys:handle_debug(Deb, {ch4, write_debug}, ch4, {in, {free, Ch}}), Chs2 = free(Ch, Chs), loop(Chs2, Parent, Deb2); {system, From, Request} -> sys:handle_system_msg(Request, From, Parent, ch4, Deb, Chs) end. system_continue(Parent, Deb, Chs) -> loop(Chs, Parent, Deb). system_terminate(Reason, Parent, Deb, Chs) -> exit(Reason). write_debug(Dev, Event, Name) -> io:format(Dev, "~p event = ~p~n", [Name, Event]).</pre></div> <p>Example on how the simple debugging functions in <span class="code">sys</span> can be used for <span class="code">ch4</span> as well:</p> <div class="example"><pre> % <span class="bold_code">erl</span> Erlang (BEAM) emulator version 5.2.3.6 [hipe] [threads:0] Eshell V5.2.3.6 (abort with ^G) 1> <span class="bold_code">ch4:start_link().</span> {ok,<0.30.0>} 2> <span class="bold_code">sys:statistics(ch4, true).</span> ok 3> <span class="bold_code">sys:trace(ch4, true).</span> ok 4> <span class="bold_code">ch4:alloc().</span> ch4 event = {in,alloc,<0.25.0>} ch4 event = {out,{ch4,ch1},<0.25.0>} ch1 5> <span class="bold_code">ch4:free(ch1).</span> ch4 event = {in,{free,ch1}} ok 6> <span class="bold_code">sys:statistics(ch4, get).</span> {ok,[{start_time,{{2003,6,13},{9,47,5}}}, {current_time,{{2003,6,13},{9,47,56}}}, {reductions,109}, {messages_in,2}, {messages_out,1}]} 7> <span class="bold_code">sys:statistics(ch4, false).</span> ok 8> <span class="bold_code">sys:trace(ch4, false).</span> ok 9> <span class="bold_code">sys:get_status(ch4).</span> {status,<0.30.0>, {module,ch4}, [[{'$ancestors',[<0.25.0>]},{'$initial_call',{ch4,init,[<0.25.0>]}}], running,<0.25.0>,[], [ch1,ch2,ch3]]}</pre></div> <h4>Starting the Process</h4> <p>A function in the <span class="code">proc_lib</span> module should be used to start the process. There are several possible functions, for example <span class="code">spawn_link/3,4</span> for asynchronous start and <span class="code">start_link/3,4,5</span> for synchronous start.</p> <p>A process started using one of these functions will store information that is needed for a process in a supervision tree, for example about the ancestors and initial call.</p> <p>Also, if the process terminates with another reason than <span class="code">normal</span> or <span class="code">shutdown</span>, a crash report (see SASL User's Guide) is generated.</p> <p>In the example, synchronous start is used. The process is started by calling <span class="code">ch4:start_link()</span>:</p> <div class="example"><pre> start_link() -> proc_lib:start_link(ch4, init, [self()]).</pre></div> <p><span class="code">ch4:start_link</span> calls the function <span class="code">proc_lib:start_link</span>. This function takes a module name, a function name and an argument list as arguments and spawns and links to a new process. The new process starts by executing the given function, in this case <span class="code">ch4:init(Pid)</span>, where <span class="code">Pid</span> is the pid (<span class="code">self()</span>) of the first process, that is the parent process.</p> <p>In <span class="code">init</span>, all initialization including name registration is done. The new process must also acknowledge that it has been started to the parent:</p> <div class="example"><pre> init(Parent) -> ... proc_lib:init_ack(Parent, {ok, self()}), loop(...).</pre></div> <p><span class="code">proc_lib:start_link</span> is synchronous and does not return until <span class="code">proc_lib:init_ack</span> has been called.</p> <h4>Debugging</h4> <a name="debug"></a> <p>To support the debug facilites in <span class="code">sys</span>, we need a <strong>debug structure</strong>, a term <span class="code">Deb</span> which is initialized using <span class="code">sys:debug_options/1</span>:</p> <div class="example"><pre> init(Parent) -> ... Deb = sys:debug_options([]), ... loop(Chs, Parent, Deb).</pre></div> <p><span class="code">sys:debug_options/1</span> takes a list of options as argument. Here the list is empty, which means no debugging is enabled initially. See <span class="code">sys(3)</span> for information about possible options.</p> <p>Then for each <strong>system event</strong> that we want to be logged or traced, the following function should be called.</p> <div class="example"><pre> sys:handle_debug(Deb, Func, Info, Event) => Deb1</pre></div> <ul> <li> <p><span class="code">Deb</span> is the debug structure.</p> </li> <li> <p><span class="code">Func</span> is a tuple <span class="code">{Module, Name}</span> (or a fun) and should specify a (user defined) function used to format trace output. For each system event, the format function is called as <span class="code">Module:Name(Dev, Event, Info)</span>, where:</p> <ul> <li> <p><span class="code">Dev</span> is the IO device to which the output should be printed. See <span class="code">io(3)</span>.</p> </li> <li> <p><span class="code">Event</span> and <span class="code">Info</span> are passed as-is from <span class="code">handle_debug</span>.</p> </li> </ul> </li> <li> <p><span class="code">Info</span> is used to pass additional information to <span class="code">Func</span>, it can be any term and is passed as-is.</p> </li> <li> <p><span class="code">Event</span> is the system event. It is up to the user to define what a system event is and how it should be represented, but typically at least incoming and outgoing messages are considered system events and represented by the tuples <span class="code">{in,Msg[,From]}</span> and <span class="code">{out,Msg,To}</span>, respectively.</p> </li> </ul> <p><span class="code">handle_debug</span> returns an updated debug structure <span class="code">Deb1</span>.</p> <p>In the example, <span class="code">handle_debug</span> is called for each incoming and outgoing message. The format function <span class="code">Func</span> is the function <span class="code">ch4:write_debug/3</span> which prints the message using <span class="code">io:format/3</span>.</p> <div class="example"><pre> loop(Chs, Parent, Deb) -> receive {From, alloc} -> Deb2 = sys:handle_debug(Deb, {ch4, write_debug}, ch4, {in, alloc, From}), {Ch, Chs2} = alloc(Chs), From ! {ch4, Ch}, Deb3 = sys:handle_debug(Deb2, {ch4, write_debug}, ch4, {out, {ch4, Ch}, From}), loop(Chs2, Parent, Deb3); {free, Ch} -> Deb2 = sys:handle_debug(Deb, {ch4, write_debug}, ch4, {in, {free, Ch}}), Chs2 = free(Ch, Chs), loop(Chs2, Parent, Deb2); ... end. write_debug(Dev, Event, Name) -> io:format(Dev, "~p event = ~p~n", [Name, Event]).</pre></div> <h4>Handling System Messages</h4> <a name="msg"></a> <p><strong>System messages</strong> are received as:</p> <div class="example"><pre> {system, From, Request}</pre></div> <p>The content and meaning of these messages do not need to be interpreted by the process. Instead the following function should be called:</p> <div class="example"><pre> sys:handle_system_msg(Request, From, Parent, Module, Deb, State)</pre></div> <p>This function does not return. It will handle the system message and then call:</p> <div class="example"><pre> Module:system_continue(Parent, Deb, State)</pre></div> <p>if process execution should continue, or:</p> <div class="example"><pre> Module:system_terminate(Reason, Parent, Deb, State)</pre></div> <p>if the process should terminate. Note that a process in a supervision tree is expected to terminate with the same reason as its parent.</p> <ul> <li> <span class="code">Request</span> and <span class="code">From</span> should be passed as-is from the system message to the call to <span class="code">handle_system_msg</span>.</li> <li> <span class="code">Parent</span> is the pid of the parent.</li> <li> <span class="code">Module</span> is the name of the module.</li> <li> <span class="code">Deb</span> is the debug structure.</li> <li> <span class="code">State</span> is a term describing the internal state and is passed to <span class="code">system_continue</span>/<span class="code">system_terminate</span>.</li> </ul> <p>In the example:</p> <div class="example"><pre> loop(Chs, Parent, Deb) -> receive ... {system, From, Request} -> sys:handle_system_msg(Request, From, Parent, ch4, Deb, Chs) end. system_continue(Parent, Deb, Chs) -> loop(Chs, Parent, Deb). system_terminate(Reason, Parent, Deb, Chs) -> exit(Reason).</pre></div> <p>If the special process is set to trap exits, note that if the parent process terminates, the expected behavior is to terminate with the same reason:</p> <div class="example"><pre> init(...) -> ..., process_flag(trap_exit, true), ..., loop(...). loop(...) -> receive ... {'EXIT', Parent, Reason} -> ..maybe some cleaning up here.. exit(Reason); ... end.</pre></div> <h3><a name="id73359">6.3 User-Defined Behaviours</a></h3> <p>To implement a user-defined behaviour, write code similar to code for a special process but calling functions in a callback module for handling specific tasks.</p> <p>If it is desired that the compiler should warn for missing callback functions, as it does for the OTP behaviours, add callback attributes in the behaviour module to describe the expected callbacks:</p> <div class="example"><pre> -callback Name1(Arg1_1, Arg1_2, ..., Arg1_N1) -> Res1. -callback Name2(Arg2_1, Arg2_2, ..., Arg2_N2) -> Res2. ... -callback NameM(ArgM_1, ArgM_2, ..., ArgM_NM) -> ResM.</pre></div> <p>where <span class="code">NameX</span> are the names of the expected callbacks and <span class="code">ArgX_Y</span>, <span class="code">ResX</span> are types as they are described in Specifications for functions in <span class="bold_code"><a href="../reference_manual/typespec.html">Types and Function Specifications</a></span>. The whole syntax of spec attributes is supported by callback attributes.</p> <p>Alternatively you may directly implement and export the function:</p> <div class="example"><pre> behaviour_info(callbacks) -> [{Name1,Arity1},...,{NameN,ArityN}].</pre></div> <p>where each <span class="code">{Name,Arity}</span> specifies the name and arity of a callback function. This function is otherwise automatically generated by the compiler using the callback attributes.</p> <p>When the compiler encounters the module attribute <span class="code">-behaviour(Behaviour).</span> in a module <span class="code">Mod</span>, it will call <span class="code">Behaviour:behaviour_info(callbacks)</span> and compare the result with the set of functions actually exported from <span class="code">Mod</span>, and issue a warning if any callback function is missing.</p> <p>Example:</p> <div class="example"><pre> %% User-defined behaviour module -module(simple_server). -export([start_link/2,...]). -callback init(State :: term()) -> 'ok'. -callback handle_req(Req :: term(), State :: term()) -> {'ok', Reply :: term()}. -callback terminate() -> 'ok'. %% Alternatively you may define: %% %% -export([behaviour_info/1]). %% behaviour_info(callbacks) -> %% [{init,1}, %% {handle_req,2}, %% {terminate,0}]. start_link(Name, Module) -> proc_lib:start_link(?MODULE, init, [self(), Name, Module]). init(Parent, Name, Module) -> register(Name, self()), ..., Dbg = sys:debug_options([]), proc_lib:init_ack(Parent, {ok, self()}), loop(Parent, Module, Deb, ...). ...</pre></div> <p>In a callback module:</p> <div class="example"><pre> -module(db). -behaviour(simple_server). -export([init/0, handle_req/2, terminate/0]). ...</pre></div> </div> <div class="footer"> <hr> <p>Copyright © 1997-2012 Ericsson AB. All Rights Reserved.</p> </div> </div> </div></body> </html>