Search code examples
functional-programmingerlangerlang-otp

Erlang OTP supervisor exits on my chat app when starting


I have developed a chat app and its server is 'message_server' here. This is a distributed app and I can spawn multiple chat users on multiple nodes by giving an atomic name for each of them. The messaging between two chat users are done by sending a message to the chat user's node. I can not start this server with a supervisor. How to solve this problem. I need the supervisor to supervise the chat users.

message_server code

-module(message_server).

-behaviour(gen_server).

-export([send_message/2, receive_message/3, start_link/1, stop/0, recv_msg/1, readyto_send/1]).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2,
  code_change/3]).

-define(SERVER, ?MODULE).

-record(message_server_state, {from, to, msgsent, msgreceived}).
%%%===================================================================
%%% Spawning and gen_server implementation
%%%===================================================================

start_link(Name) ->
  gen_server:start_link({local, ?MODULE}, ?MODULE, Name, []).

init(Name) ->
  io:format("~p is connected with the server...~n", [Name]),
  {ok, #message_server_state{
    from = atom_to_list(node()),
    to = [],
    msgsent = [],
    msgreceived = []
  }}.
stop() ->
  gen_server:stop(?MODULE).



send_message(To, Msg) ->
  gen_server:call({?MODULE, node()}, {send, To, Msg}).

receive_message(Sender, To, Msg) ->
  gen_server:call({?MODULE, list_to_atom(To)}, {reciv, Sender, Msg}).

recv_msg(Msg)->
  gen_server:call({?MODULE, node()}, {recive, Msg}).

readyto_send(To)->
  gen_server:call({?MODULE, list_to_atom(To)}, {ready, To}).

handle_call({send, To, Msg}, _From, State = #message_server_state{to = Receivers, msgsent = Msgsent, from = Sender}) ->
  io:format("Sent message: ~p~n", [Msg]),
%%  chat_fsm:message_send(Msg, To),--toDo add later--
  receive_message(Sender, To, Msg),
  {reply, ok, State#message_server_state{msgsent = [Msg | Msgsent], to = [To | Receivers]}};


handle_call({reciv, Sender, Msg}, _From, State = #message_server_state{msgreceived = Msgreceived}) ->
  io:format("Sent by: ~p~n", [Sender]),
  io:format("Message: ~p~n", [Msg]),
  M = database_server:getalldb(Sender),
  io:format("SENDER-DETAILS>>: ~p~n",[M]),
  {reply, ok, State#message_server_state{msgreceived = [Msg | Msgreceived]}};

handle_call({recive, Msg}, _From, State = #message_server_state{msgreceived = Msgreceived}) ->
  io:format("Message: ~p~n", [Msg]),
  {reply, ok, State#message_server_state{msgreceived = [Msg | Msgreceived]}}.
%%--toDo add later--
%%handle_call({ready, To}, _From, State) ->%%  chat_fsm:ready_to_send(To),
%%  {reply, ok, State}.

handle_cast(_Request, State = #message_server_state{}) ->
  {noreply, State}.

handle_info(_Info, State = #message_server_state{}) ->
  {noreply, State}.

terminate(_Reason, _State = #message_server_state{}) ->
  ok.

code_change(_OldVsn, State = #message_server_state{}, _Extra) ->
  {ok, State}.

chat_sup supervisor

-module(chat_sup).

-behaviour(supervisor).

-export([start_link/0, init/1, start_link_shell2/0]).

start_link_shell2()->
  {ok, Pid2}= supervisor:start_link({global,?MODULE}, ?MODULE,[]),
  unlink(Pid2).

start_link() ->
  supervisor:start_link({global, ?MODULE}, ?MODULE, []).

init([]) ->AChild = #{id => 'message_server',
    start => {'message_server', start_link, []},
    restart => permanent,
    shutdown => infinity,
    type => worker,
    modules => ['message_server']},

  {ok, {#{strategy => one_for_all,
    intensity => 5,
    period => 30},
    [AChild]}
  }.

I get this error when starting supervisor

(john@DESKTOP-RD414DV)5> chat_sup:start_link_shell2().
=SUPERVISOR REPORT==== 21-Sep-2022::05:49:46.626000 ===
    supervisor: {global,chat_sup}
    errorContext: start_error
    reason: {'EXIT',
                {undef,
                    [{message_server,start_link,[],[]},
                     {supervisor,do_start_child_i,3,
                         [{file,"supervisor.erl"},{line,414}]},
                     {supervisor,do_start_child,2,
                         [{file,"supervisor.erl"},{line,400}]},
                     {supervisor,'-start_children/2-fun-0-',3,
                         [{file,"supervisor.erl"},{line,384}]},
                     {supervisor,children_map,4,
                         [{file,"supervisor.erl"},{line,1250}]},
                     {supervisor,init_children,2,
                         [{file,"supervisor.erl"},{line,350}]},
                     {gen_server,init_it,2,
                         [{file,"gen_server.erl"},{line,848}]},
                     {gen_server,init_it,6,
                         [{file,"gen_server.erl"},{line,811}]}]}}
    offender: [{pid,undefined},
               {id,message_server},
               {mfargs,{message_server,start_link,[]}},
               {restart_type,permanent},
               {significant,false},
               {shutdown,infinity},
               {child_type,worker}]



** exception exit: {shutdown,
                        {supervisor,'-start_children/2-fun-0-',3,
                         [{file,"supervisor.erl"},{line,384}]},
                        {supervisor,children_map,4,
                         [{file,"supervisor.erl"},{line,1250}]},
                        {supervisor,init_children,2,
                         [{file,"supervisor.erl"},{line,350}]},
                        {gen_server,init_it,2,
                         [{file,"gen_server.erl"},{line,848}]},
                        {gen_server,init_it,6,
                         [{file,"gen_server.erl"},{line,811}]}]}}}}

Solution

  • The start mfa (message_server:start_link/0) does not match message_server:start_link/1 signature

    - start => {'message_server', start_link, []}
    + start => {'message_server', start_link, ['message_server_name']}
    

    or implement message_server:start_link/0 as

    start_link() ->
      gen_server:start_link({local, ?MODULE}, ?MODULE, Name, [?MODULE]).