suggested patches, c.erl, proc_lib.erl

Ulf Wiger <>
Fri Feb 28 17:38:07 CET 2003


(This is not sent directly to erlang-patches, partly because
I'd like some feedback on it. Please read on.)

Personally, I like processes started with proc_lib when it
comes to debugging (when SASL is running, you get crash
reports), but I also like the convention of spawning
processes using a fun, e.g.

start_registered(server, fun() -> start_server(Port, Me) end).

(partly because you don't have to export the init function,
and partly because it makes it easier to follow the logic --
and you can use 'tags' in Emacs to jump directly to the init
function. ;)

As I'm working with Joe's excellent UBF server, I decided to
try to marry the two. Joe used spawning with funs, but
(obviously) not proc_lib. The attached diff makes it
possible to call proc_lib:spawn(fun() -> ... end), and
proc_lib:spawn_link(fun() -> ... end), etc. (I did _not_
modify proc_lib:start(), mainly because it got a bit
confusing with arities.)

I also modified c.erl to make the output from i() a little
more descriptive. Here, I'd welcome a way to present
processes started with a fun in a better way. Example:

<0.62.0>              proc_socket_server:cold_start/4    233 196  0
picoSocketServer_8800 proc_socket_server:socket_loop/5    11
<0.63.0>              supervisor:'cath.server.superviso  233 165    0
'cath.server.supervis gen_server:loop/6                   12
<0.64.0>              proc_socket_server:start_child/3   233  22    0
                      prim_inet:accept0/2                 15
<0.65.0>              #Fun:ubf_utils.0[#Fun<plugin_hand  233  62    0
                      plugin_handler:manager_loop/3       10
<0.66.0>              #Fun:ubf_utils.0[#Fun<plugin_hand  377  71    0
                      plugin_handler:manager_loop/3       10
<0.67.0>              #Fun:ubf_utils.0[#Fun<plugin_hand  233  70    0
                      plugin_handler:manager_loop/3       10
<0.68.0>              #Fun:ubf_utils.0[#Fun<plugin_hand  233  74    0
                      plugin_handler:manager_loop/3       10
<0.69.0>              'cath.server.control':init/1       233  30    0
control               gen_server:loop/6                   12
<0.98.0>              shell:evaluator/3                  987  150353    0
                      c:pinfo/1                           38
<0.120.0>             #Fun:erl_eval.19[{eval,{shell,loc  233  44    0
                      timer:sleep/1                       21
Total  43056  1017785    0

If it's not entirely obvious, the information concerning
funs consists of the module name and first digit in the
"name" of the fun (e.g. #Fun<erl_eval.19.280769>), followed
by the results of the call erlang:fun_info(F, env) -- that
is, the bindings.

Comments welcome.

/Uffe

-- 
Ulf Wiger, Senior Specialist,
   / / /   Architecture & Design of Carrier-Class Software
  / / /    Strategic Product & System Management
 / / /     Ericsson AB, Connectivity and Control Nodes


-------------- next part --------------
251a252,255
> mfa_string(F) when function(F) ->
>     Str = fun_string(F),
>     {env,Env} = erlang:fun_info(F, env),
>     io_lib:format("#Fun:~s~p", [Str,Env]);
256a261,268
> fun_string(F) ->
>     Str = erlang:fun_to_list(F),
>     {match,A,B} = regexp:match(Str,"<.*>"),
>     Info = string:substr(Str,A+1,B-2),
>     {match,C,1} = regexp:match(lists:reverse(Info),"\\."),
>     string:substr(Info,1,length(Info)-C).
>     
> 
292c304
< 	{proc_lib, init_p, 5} ->
---
> 	{proc_lib, init_p, _} ->
-------------- next part --------------
27,28c27,29
< -export([spawn/3,spawn_link/3,spawn/4,spawn_link/4,
< 	 spawn_opt/4,
---
> -export([spawn/1,spawn_link/1, spawn/2, spawn_link/2,
> 	 spawn/3,spawn_link/3,spawn/4,spawn_link/4,
> 	 spawn_opt/2, spawn_opt/4,
31c32
< 	 init_p/5,format/1,initial_call/1,translate_initial_call/1]).
---
> 	 init_p/3,init_p/5,format/1,initial_call/1,translate_initial_call/1]).
32a34,38
> spawn(F) when function(F) ->
>     Parent = get_my_name(),
>     Ancestors = get_ancestors(),
>     erlang:spawn(proc_lib,init_p,[Parent,Ancestors,F]).
> 
37a44,48
> spawn_link(F) when function(F) ->
>     Parent = get_my_name(),
>     Ancestors = get_ancestors(),
>     erlang:spawn_link(proc_lib,init_p,[Parent,Ancestors,F]).
> 
42a54,58
> spawn(Node, F) when function(F) ->
>     Parent = get_my_name(),
>     Ancestors = get_ancestors(),
>     erlang:spawn(Node,proc_lib,init_p,[Parent,Ancestors,F]).
> 
47a64,68
> spawn_link(Node,F) when function(F) ->
>     Parent = get_my_name(),
>     Ancestors = get_ancestors(),
>     erlang:spawn_link(Node,proc_lib,init_p,[Parent,Ancestors,F]).
> 
53c74,78
< 
---
> spawn_opt(F, Opts) when function(F) ->
>     Parent = get_my_name(),
>     Ancestors = get_ancestors(),
>     erlang:spawn_opt(proc_lib,init_p,[Parent,Ancestors,F],Opts).
>     
67a93,98
> init_p(Parent,Ancestors,F) when function(F) ->
>     put('$ancestors',[Parent|Ancestors]),
>     put('$initial_call',F),
>     Result = (catch F()),
>     exit_p(Result,F).
>     
73c104
<     exit_p(Result,M,F,A).
---
>     exit_p(Result,{M,F,A}).
75,76c106,107
< exit_p({'EXIT',Reason},M,F,A) ->
<     crash_report(Reason,M,F,A),
---
> exit_p({'EXIT',Reason},StartF) ->
>     crash_report(Reason,StartF),
78c109
< exit_p(Reason,_,_,_) ->
---
> exit_p(Reason,_) ->
151a183,184
> 	{value,{_,F}} when function(F) ->
> 	    F;
162a196
> 
166a201,202
> 	F when function(F) ->
> 	    F;
195,199c231,235
<     
< crash_report(normal,_,_,_)      -> ok;
< crash_report(shutdown,_,_,_)    -> ok;
< crash_report(Reason,M,F,A) ->
<     OwnReport = my_info(Reason,M,F,A),
---
> 
> crash_report(normal,_)      -> ok;
> crash_report(shutdown,_)    -> ok;
> crash_report(Reason,StartF) ->
>     OwnReport = my_info(Reason,StartF),
205c241
< my_info(Reason,M,F,A) ->
---
> my_info(Reason,StartF) ->
209c245
<      {initial_call, {M, F, A}},
---
>      {initial_call, StartF},


More information about the erlang-questions mailing list