Related
Hello i am trying to run a supervisor whose workers are not gen_server(s).
My supervisor is defined in the same module as the worker for brevity:
I keep getting this error and i have tried putting the MFA attribute in [ ] to no avail.I have also put the ChildSpec in [ ].
What am i missing ?
I do not want my supervisor to have any workers when starting it.
Error
> X=sup:start_link().
> ** exception error: no match of right hand side value {error,
> {bad_start_spec,[]}}
> in function sup:start_link/0 (c:/Erlang/ProcessPool/sup.erl, line 6)
> =CRASH REPORT==== 5-Apr-2020::22:20:32.918000 === crasher:
> initial call: supervisor:sup/1
> pid: <0.280.0>
> registered_name: []
> exception exit: {bad_start_spec,[]}
> in function gen_server:init_it/6 (gen_server.erl, line 358)
> ancestors: [<0.273.0>]
> message_queue_len: 0
> messages: []
> links: [<0.273.0>]
> dictionary: []
> trap_exit: true
> status: running
> heap_size: 376
> stack_size: 27
> reductions: 205 neighbours:
Module
-module(sup).
-behaviour(supervisor).
-compile([export_all]).
start_link() ->
{ok, Pid} = supervisor:start_link({local, ?MODULE}, ?MODULE, []),
Pid.
init(_Args) ->
RestartStrategy = {simple_one_for_one, 10, 60},
{ok, {RestartStrategy,[]}}.
add(Sup,Value)-> #adding child
ChildSpec = {
ch1,
{sup, start, [Value]},
permanent,
brutal_kill,
worker,
[ch1]
},
supervisor:start_child(Sup,ChildSpec).
start([Value])-> #child's start_link equivalent (non-genserver)
spawn_link(?MODULE,initworker,[self(),Value]).
initworker(From,Value)-> #child's init
receive
MSG->From ! {got_msg,Value,MSG}
end.
As you using simple_one_for_one, You should define ChildSpec in init and all children use the same ChildSpec .
If you need different, then use 'one_for_one' strategy instead.
For simple_one_for_one:
The second argument of supervisor:start_child/2 must be a list which will be combined with default arguments to child start function arguments defined in ChildSpec.
Here I quickly modified the code to make it work for you.
-module(sup).
-behaviour(supervisor).
-compile([export_all]).
start_link() ->
{ok, Pid} = supervisor:start_link({local, ?MODULE}, ?MODULE, []),
Pid.
init(_Args) ->
RestartStrategy = {simple_one_for_one, 10, 60},
ChildSpec = {
ch1,
{sup, start, []},
permanent,
brutal_kill,
worker,
[sup]
},
{ok, {RestartStrategy,[ChildSpec]}}.
add(Sup,Value)->
supervisor:start_child(Sup,[Value]).
start(Value)->
P = spawn(?MODULE, initworker,[]),
P!{self(),Value},
{ok,P}.
initworker()->
receive
{From, MSG} -> io:format(" Value is ~p~n", [MSG])
end.
I'm very new to OTP, I'm trying to create simple example to understand supervisor behaviour:
Here is simple increment server
-module( inc_serv ).
-behaviour( gen_server ).
-export( [ start/0, inc/1, stop/0 ] ).
-export( [ init/1, handle_call/3, terminate/2 ] ).
start() ->
gen_server:start_link( { local, ?MODULE }, ?MODULE, no_args, [] ).
stop() ->
gen_server:call( ?MODULE, stop ).
inc( Num ) ->
gen_server:call( ?MODULE, { num, Num } ).
init( no_args ) ->
io:format( "~p~n", [ "Increment server started :)" ] ),
{ ok, no_state }.
handle_call( { num, Num }, _From, no_state ) ->
{ reply, Num + 1, no_state };
handle_call( stop, _From, no_state ) ->
{ stop, normal, ok, no_state }.
terminate( Reason, no_state ) ->
io:format( "~p~n", [ "Increment server stopped" ] ).
And I'd like to make it supervised by this module:
-module( supervisor_inc ).
-behaviour( supervisor ).
-export( [ start/0 ] ).
-export( [ init/1 ] ).
start() ->
supervisor:start_link( { local, ?MODULE }, ?MODULE, no_args ).
init( no_args ) ->
process_flag( trap_exit, true ),
Supervisor_Spec = { one_for_one, 1, 1 },
IncServ_Spec = {
inc_serv,
{ inc_serv, start, [] },
permanent, 2000, worker, [ inc_serv ] },
{ ok, { Supervisor_Spec, [ IncServ_Spec ] } }.
After that I've performed in erlang shell next steps:
1>
1> c(inc_serv).
{ok,inc_serv}
2>
2> c(supervisor_inc).
{ok,supervisor_inc}
3>
3> supervisor_inc:start().
"Increment server started :)"
{ok,<0.43.0>}
4>
4> inc_serv:inc( 7 ).
8
5> inc_serv:inc( 8 ).
9
After this I've tried next (as I expected I've got error):
6> inc_serv:inc( bad_arg ).
"Increment server stopped"
"Increment server started :)"
=ERROR REPORT==== 23-Aug-2012::19:32:06 ===
** Generic server inc_serv terminating
** Last message in was {num,bad_arg}
** When Server state == no_state
** Reason for termination ==
** {badarith,[{inc_serv,handle_call,3,[{file,"inc_serv.erl"},{line,22}]},
{gen_server,handle_msg,5,[{file,"gen_server.erl"},{line,588}]},
{proc_lib,init_p_do_apply,3,
[{file,"proc_lib.erl"},{line,227}]}]}
=ERROR REPORT==== 23-Aug-2012::19:32:06 ===
** Generic server supervisor_inc terminating
** Last message in was {'EXIT',<0.31.0>,
{{{badarith,
[{inc_serv,handle_call,3,
[{file,"inc_serv.erl"},{line,22}]},
{gen_server,handle_msg,5,
[{file,"gen_server.erl"},{line,588}]},
{proc_lib,init_p_do_apply,3,
[{file,"proc_lib.erl"},{line,227}]}]},
{gen_server,call,[inc_serv,{num,bad_arg}]}},
[{gen_server,call,2,
[{file,"gen_server.erl"},{line,180}]},
{erl_eval,do_apply,6,
[{file,"erl_eval.erl"},{line,576}]},
{shell,exprs,7,[{file,"shell.erl"},{line,668}]},
{shell,eval_exprs,7,
[{file,"shell.erl"},{line,623}]},
{shell,eval_loop,3,
[{file,"shell.erl"},{line,608}]}]}}
** When Server state == {state,
{local,supervisor_inc},
one_for_one,
[{child,<0.48.0>,inc_serv,
{inc_serv,start,[]},
permanent,2000,worker,
[inc_serv]}],
undefined,1,1,
[{1345,739526,107495}],
supervisor_inc,no_args}
** Reason for termination ==
** {{{badarith,[{inc_serv,handle_call,3,[{file,"inc_serv.erl"},{line,22}]},
{gen_server,handle_msg,5,[{file,"gen_server.erl"},{line,588}]},
{proc_lib,init_p_do_apply,3,
[{file,"proc_lib.erl"},{line,227}]}]},
{gen_server,call,[inc_serv,{num,bad_arg}]}},
[{gen_server,call,2,[{file,"gen_server.erl"},{line,180}]},
{erl_eval,do_apply,6,[{file,"erl_eval.erl"},{line,576}]},
{shell,exprs,7,[{file,"shell.erl"},{line,668}]},
{shell,eval_exprs,7,[{file,"shell.erl"},{line,623}]},
{shell,eval_loop,3,[{file,"shell.erl"},{line,608}]}]}
** exception exit: {{badarith,[{inc_serv,handle_call,3,
[{file,"inc_serv.erl"},{line,22}]},
{gen_server,handle_msg,5,
[{file,"gen_server.erl"},{line,588}]},
{proc_lib,init_p_do_apply,3,
[{file,"proc_lib.erl"},{line,227}]}]},
{gen_server,call,[inc_serv,{num,bad_arg}]}}
in function gen_server:call/2 (gen_server.erl, line 180)
After this I've expected - my supervisor to restart inc_serv. But it didn't:
7> inc_serv:inc( 8 ).
** exception exit: {noproc,{gen_server,call,[inc_serv,{num,8}]}}
in function gen_server:call/2 (gen_server.erl, line 180)
Could you help me to understand what happened? And how should I rewrite my supervisor, to make it able to restart inc_serv
Thanks
This is actually a kind of race condition.
As you might know, the Erlang shell itself is a normal Erlang process. When you start your supervisor from the shell, the supervisor is linked to the shell (because you use supervisor:start_link/3).
When you call your gen_server process, that process crashes (and is correctly restarted by the supervisor, as you can see by the subsequent "Increment server started :)" output).
However, at the same time, your call to gen_server:call/2 will result in the same crash (a gen_server crashing during the call will emit the same crash through the gen_server:call/2 function). This then crashes the shell process, which is linked to your supervisor, which in turn crashes with the same reason (badarith).
Basically, your supervisor is backstabbed by your shell process, after it loyally restarted your gen_server. Like so:
+---------(6)exit----------+ +---------(5)restart---------+
| | | |
| v | v
Shell ---(1)start_link---> supervisor ---(2)start_link---> gen_server
| ^ ^ | ^ | ^
| | | | | | |
| | | +---------(7)exit---------+ | |
| | | | |
| +-------------------------+--------------(4)exit------------+ |
| |
+---------------------------(3)call--------------------------------+
You can avoid this by calling catch inc_serv:inc(bad_arg). in your shell:
90> inc_serv:inc(7).
8
91> catch inc_serv:inc(bad_arg).
"Increment server stopped"
=ERROR REPORT==== 23-Aug-2012::22:10:02 ===
** Generic server inc_serv terminating
** Last message in was {num,bad_arg}
** When Server state == no_state
** Reason for termination ==
** {badarith,[{inc_serv,handle_call,3,[{file,"inc_serv.erl"},{line,20}]},
{gen_server,handle_msg,5,[{file,"gen_server.erl"},{line,588}]},
{proc_lib,init_p_do_apply,3,
[{file,"proc_lib.erl"},{line,227}]}]}
"Increment server started :)"
{'EXIT',{{badarith,[{inc_serv,handle_call,3,
[{file,"inc_serv.erl"},{line,20}]},
{gen_server,handle_msg,5,
[{file,"gen_server.erl"},{line,588}]},
{proc_lib,init_p_do_apply,3,
[{file,"proc_lib.erl"},{line,227}]}]},
{gen_server,call,[inc_serv,{num,bad_arg}]}}}
92> inc_serv:inc(7).
8
In the code below, why is the module prime_server not loading?
-module(prime_server).
-behaviour(gen_server).
-export([new_prime/1, start_link/0]).
%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
new_prime(N) ->
%% 20000 is a timeout (ms)
gen_server:call(?MODULE, {prime, N}, 20000).
init([]) ->
%% Note we must set trap_exit = true if we
%% want terminate/2 to be called when the application
%% is stopped
process_flag(trap_exit, true),
io:format("~p starting~n" ,[?MODULE]),
{ok, 0}.
handle_call({prime, K}, _From, N) ->
{reply, make_new_prime(K), N+1}.
handle_cast(_Msg, N) -> {noreply, N}.
handle_info(_Info, N) -> {noreply, N}.
terminate(_Reason, _N) ->
io:format("~p stopping~n" ,[?MODULE]),
ok.
code_change(_OldVsn, N, _Extra) -> {ok, N}.
make_new_prime(K) ->
if
K > 100 ->
alarm_handler:set_alarm(tooHot),
N = lib_primes:make_prime(K),
alarm_handler:clear_alarm(tooHot),
N;
true ->
lib_primes:make_prime(K)
end.
OUTPUT:
$ erl -boot start_sasl
1>c(prime_server).
{ok,prime_server}
2>c(my_alarm_handler).
my_alarm_handler.erl:2: Warning: undefined callback function code_change/3 (behaviour 'gen_event')
my_alarm_handler.erl:19: Warning: variable 'Reply' is unused
{ok,my_alarm_handler}
3> {ok, Pid} = prime_server:start_link().
prime_server starting
{ok, <0.73.0>}
4> prime_server:new_prime(6).
prime_server stopping
=ERROR REPORT==== 24-Mar-2014::10:59:39 ===
** Generic server prime_server terminating
** Last message in was {prime,6}
** When Server state == 0
** Reason for termination ==
** {'module could not be loaded',
[{lib_primes,make_prime,[6],[]},
{prime_server,handle_call,3,[{file,"prime_server.erl"},{line,21}]},
{gen_server,handle_msg,5,[{file,"gen_server.erl"},{line,585}]},
{proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,239}]}]}
=CRASH REPORT==== 24-Mar-2014::10:59:39 ===
crasher:
initial call: prime_server:init/1
pid: <0.73.0>
registered_name: prime_server
exception exit: {undef,
[{lib_primes,make_prime,[6],[]},
{prime_server,handle_call,3,
[{file,"prime_server.erl"},{line,21}]},
{gen_server,handle_msg,5,
[{file,"gen_server.erl"},{line,585}]},
{proc_lib,init_p_do_apply,3,
[{file,"proc_lib.erl"},{line,239}]}]}
in function gen_server:terminate/6 (gen_server.erl, line 744)
ancestors: [<0.71.0>]
messages: []
links: [<0.71.0>]
dictionary: []
trap_exit: true
status: running
heap_size: 610
stack_size: 27
reductions: 181
neighbours:
neighbour: [{pid,<0.71.0>},
{registered_name,[]},
{initial_call,{erlang,apply,2}},
{current_function,{gen,do_call,4}},
{ancestors,[]},
{messages,[]},
{links,[<0.27.0>,<0.73.0>]},
{dictionary,[]},
{trap_exit,false},
{status,waiting},
{heap_size,610},
{stack_size,36},
{reductions,1303}]
** exception exit: undef
in function lib_primes:make_prime/1
called as lib_primes:make_prime(6)
in call from prime_server:handle_call/3 (prime_server.erl, line 21)
in call from gen_server:handle_msg/5 (gen_server.erl, line 585)
in call from proc_lib:init_p_do_apply/3 (proc_lib.erl, line 239)
9> gen_server:call(prime_server, 6).
** exception exit: {noproc,{gen_server,call,[prime_server,6]}}
in function gen_server:call/2 (gen_server.erl, line 180)
10> gen_server:call(prime_server, new_prime, 6).
** exception exit: {noproc,{gen_server,call,[prime_server,new_prime,6]}}
in function gen_server:call/3 (gen_server.erl, line 188)
11> gen_server:call(prime_server, new_prime(5), []).
** exception error: undefined shell command new_prime/1
12> gen_server:call(prime_server, {prime, 4}, []).
** exception exit: {{function_clause,
[{gen,call,
[prime_server,'$gen_call',{prime,4},[]],
[{file,"gen.erl"},{line,147}]},
{gen_server,call,3,
[{file,"gen_server.erl"},{line,184}]},
{erl_eval,do_apply,6,
[{file,"erl_eval.erl"},{line,573}]},
{shell,exprs,7,[{file,"shell.erl"},{line,674}]},
{shell,eval_exprs,7,[{file,"shell.erl"},{line,629}]},
{shell,eval_loop,3,[{file,"shell.erl"},{line,614}]}]},
{gen_server,call,[prime_server,{prime,4},[]]}}
{'module could not be loaded',
[{lib_primes,make_prime,[6],[]},
{prime_server,handle_call,3,[{file,"prime_server.erl"},{line,21}]},
{gen_server,handle_msg,5,[{file,"gen_server.erl"},{line,585}]},
{proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,239}]}]}
From the log, you use this module lib_primes, do you have this file lib_primes.erl?
I think you should compiule and load this module lib_primes first.
I'm very new to OTP, I'm trying to create simple example to understand supervisor behaviour:
Here is simple increment server
-module( inc_serv ).
-behaviour( gen_server ).
-export( [ start/0, inc/1, stop/0 ] ).
-export( [ init/1, handle_call/3, terminate/2 ] ).
start() ->
gen_server:start_link( { local, ?MODULE }, ?MODULE, no_args, [] ).
stop() ->
gen_server:call( ?MODULE, stop ).
inc( Num ) ->
gen_server:call( ?MODULE, { num, Num } ).
init( no_args ) ->
io:format( "~p~n", [ "Increment server started :)" ] ),
{ ok, no_state }.
handle_call( { num, Num }, _From, no_state ) ->
{ reply, Num + 1, no_state };
handle_call( stop, _From, no_state ) ->
{ stop, normal, ok, no_state }.
terminate( Reason, no_state ) ->
io:format( "~p~n", [ "Increment server stopped" ] ).
And I'd like to make it supervised by this module:
-module( supervisor_inc ).
-behaviour( supervisor ).
-export( [ start/0 ] ).
-export( [ init/1 ] ).
start() ->
supervisor:start_link( { local, ?MODULE }, ?MODULE, no_args ).
init( no_args ) ->
process_flag( trap_exit, true ),
Supervisor_Spec = { one_for_one, 1, 1 },
IncServ_Spec = {
inc_serv,
{ inc_serv, start, [] },
permanent, 2000, worker, [ inc_serv ] },
{ ok, { Supervisor_Spec, [ IncServ_Spec ] } }.
After that I've performed in erlang shell next steps:
1>
1> c(inc_serv).
{ok,inc_serv}
2>
2> c(supervisor_inc).
{ok,supervisor_inc}
3>
3> supervisor_inc:start().
"Increment server started :)"
{ok,<0.43.0>}
4>
4> inc_serv:inc( 7 ).
8
5> inc_serv:inc( 8 ).
9
After this I've tried next (as I expected I've got error):
6> inc_serv:inc( bad_arg ).
"Increment server stopped"
"Increment server started :)"
=ERROR REPORT==== 23-Aug-2012::19:32:06 ===
** Generic server inc_serv terminating
** Last message in was {num,bad_arg}
** When Server state == no_state
** Reason for termination ==
** {badarith,[{inc_serv,handle_call,3,[{file,"inc_serv.erl"},{line,22}]},
{gen_server,handle_msg,5,[{file,"gen_server.erl"},{line,588}]},
{proc_lib,init_p_do_apply,3,
[{file,"proc_lib.erl"},{line,227}]}]}
=ERROR REPORT==== 23-Aug-2012::19:32:06 ===
** Generic server supervisor_inc terminating
** Last message in was {'EXIT',<0.31.0>,
{{{badarith,
[{inc_serv,handle_call,3,
[{file,"inc_serv.erl"},{line,22}]},
{gen_server,handle_msg,5,
[{file,"gen_server.erl"},{line,588}]},
{proc_lib,init_p_do_apply,3,
[{file,"proc_lib.erl"},{line,227}]}]},
{gen_server,call,[inc_serv,{num,bad_arg}]}},
[{gen_server,call,2,
[{file,"gen_server.erl"},{line,180}]},
{erl_eval,do_apply,6,
[{file,"erl_eval.erl"},{line,576}]},
{shell,exprs,7,[{file,"shell.erl"},{line,668}]},
{shell,eval_exprs,7,
[{file,"shell.erl"},{line,623}]},
{shell,eval_loop,3,
[{file,"shell.erl"},{line,608}]}]}}
** When Server state == {state,
{local,supervisor_inc},
one_for_one,
[{child,<0.48.0>,inc_serv,
{inc_serv,start,[]},
permanent,2000,worker,
[inc_serv]}],
undefined,1,1,
[{1345,739526,107495}],
supervisor_inc,no_args}
** Reason for termination ==
** {{{badarith,[{inc_serv,handle_call,3,[{file,"inc_serv.erl"},{line,22}]},
{gen_server,handle_msg,5,[{file,"gen_server.erl"},{line,588}]},
{proc_lib,init_p_do_apply,3,
[{file,"proc_lib.erl"},{line,227}]}]},
{gen_server,call,[inc_serv,{num,bad_arg}]}},
[{gen_server,call,2,[{file,"gen_server.erl"},{line,180}]},
{erl_eval,do_apply,6,[{file,"erl_eval.erl"},{line,576}]},
{shell,exprs,7,[{file,"shell.erl"},{line,668}]},
{shell,eval_exprs,7,[{file,"shell.erl"},{line,623}]},
{shell,eval_loop,3,[{file,"shell.erl"},{line,608}]}]}
** exception exit: {{badarith,[{inc_serv,handle_call,3,
[{file,"inc_serv.erl"},{line,22}]},
{gen_server,handle_msg,5,
[{file,"gen_server.erl"},{line,588}]},
{proc_lib,init_p_do_apply,3,
[{file,"proc_lib.erl"},{line,227}]}]},
{gen_server,call,[inc_serv,{num,bad_arg}]}}
in function gen_server:call/2 (gen_server.erl, line 180)
After this I've expected - my supervisor to restart inc_serv. But it didn't:
7> inc_serv:inc( 8 ).
** exception exit: {noproc,{gen_server,call,[inc_serv,{num,8}]}}
in function gen_server:call/2 (gen_server.erl, line 180)
Could you help me to understand what happened? And how should I rewrite my supervisor, to make it able to restart inc_serv
Thanks
This is actually a kind of race condition.
As you might know, the Erlang shell itself is a normal Erlang process. When you start your supervisor from the shell, the supervisor is linked to the shell (because you use supervisor:start_link/3).
When you call your gen_server process, that process crashes (and is correctly restarted by the supervisor, as you can see by the subsequent "Increment server started :)" output).
However, at the same time, your call to gen_server:call/2 will result in the same crash (a gen_server crashing during the call will emit the same crash through the gen_server:call/2 function). This then crashes the shell process, which is linked to your supervisor, which in turn crashes with the same reason (badarith).
Basically, your supervisor is backstabbed by your shell process, after it loyally restarted your gen_server. Like so:
+---------(6)exit----------+ +---------(5)restart---------+
| | | |
| v | v
Shell ---(1)start_link---> supervisor ---(2)start_link---> gen_server
| ^ ^ | ^ | ^
| | | | | | |
| | | +---------(7)exit---------+ | |
| | | | |
| +-------------------------+--------------(4)exit------------+ |
| |
+---------------------------(3)call--------------------------------+
You can avoid this by calling catch inc_serv:inc(bad_arg). in your shell:
90> inc_serv:inc(7).
8
91> catch inc_serv:inc(bad_arg).
"Increment server stopped"
=ERROR REPORT==== 23-Aug-2012::22:10:02 ===
** Generic server inc_serv terminating
** Last message in was {num,bad_arg}
** When Server state == no_state
** Reason for termination ==
** {badarith,[{inc_serv,handle_call,3,[{file,"inc_serv.erl"},{line,20}]},
{gen_server,handle_msg,5,[{file,"gen_server.erl"},{line,588}]},
{proc_lib,init_p_do_apply,3,
[{file,"proc_lib.erl"},{line,227}]}]}
"Increment server started :)"
{'EXIT',{{badarith,[{inc_serv,handle_call,3,
[{file,"inc_serv.erl"},{line,20}]},
{gen_server,handle_msg,5,
[{file,"gen_server.erl"},{line,588}]},
{proc_lib,init_p_do_apply,3,
[{file,"proc_lib.erl"},{line,227}]}]},
{gen_server,call,[inc_serv,{num,bad_arg}]}}}
92> inc_serv:inc(7).
8
I write some code to test simple_one_for_one supervisor, but it can not work, the code is:
-module(test_simple_one_for_one).
-behaviour(supervisor).
%% API
-export([start_link/0, start_fun_test/0]).
%% Supervisor callbacks
-export([init/1]).
-define(SERVER, ?MODULE).
%%--------------------------------------------------------------------
start_link() ->
{ok, Pid} = supervisor:start_link({local, ?SERVER}, ?MODULE, []).
start_fun_test() ->
supervisor:start_child(test_simple_one_for_one, []).
init([]) ->
RestartStrategy = simple_one_for_one,
MaxRestarts = 1000,
MaxSecondsBetweenRestarts = 3600,
SupFlags = {RestartStrategy, MaxRestarts, MaxSecondsBetweenRestarts},
Restart = permanent,
Shutdown = 2000,
Type = worker,
AChild = {fun_test_sup, {fun_test, run, []},
Restart, Shutdown, Type, [fun_test]},
io:format("start supervisor------ ~n"),
{ok, {SupFlags, [AChild]}}.
When I run
test_simple_one_for_one:start_link().
and
test_simple_one_for_one:start_fun_test().
in erl shell, it gives me error:
test_simple_one_for_one:start_fun_test().
** exception exit: {noproc,{gen_server,call,
[test_simple_one_for_one,{start_child,[]},infinity]}}
in function gen_server:call/3 (gen_server.erl, line 188)
If it's all the code you've written for the test, beware that when you register a supervisor child you suplly a {M, F, A} tuple which represent the function called when you start a child.
In you're case, I think it cannot simply find the fun_test:run/1 function.