[erlang-questions] Simple client handler "at the accept call" of a server

Berlin Brown berlin.brown@REDACTED
Sat Mar 8 16:17:22 CET 2008


I have some client handling code, ideally it is pretty simple; but I
keep getting this function_clause error.

Here is my test case.

1. Start the server
2. Launch a telnet session and type:
ACB<press enter> and then close the connection.
(Note: if I don't type anything and just quit, the connection closes
without error).

---------------------------

Here is the error, I receive; it doesn't seem to reach tcp_closed for
some reason.

=ERROR REPORT==== 8-Mar-2008::10:16:55 ===
** Generic server <0.30.0> terminating
** Last message in was {tcp_closed,#Port<0.90>}
** When Server state == {noreply,
                            {client_state,<0.28.0>,undefined,starting,
                                {client_info,<0.28.0>,<0.29.0>,#Port<0.90>},
                                undefined,undefined}}
** Reason for termination ==
** {function_clause,
       [{client_handler,terminate,
            [{function_clause,
                 [{client_handler,handle_info,
                      [{tcp_closed,#Port<0.90>},
                       {noreply,
                           {client_state,<0.28.0>,undefined,starting,
                               {client_info,<0.28.0>,<0.29.0>,#Port<0.90>},
                               undefined,undefined}}]},
                  {gen_server,handle_msg,5},
                  {proc_lib,init_p,5}]},
             {noreply,
                 {client_state,<0.28.0>,undefined,starting,
                     {client_info,<0.28.0>,<0.29.0>,#Port<0.90>},
                     undefined,undefined}}]},
        {gen_server,terminate,6},
        {proc_lib,init_p,5}]}
{"init terminating in
do_boot",{{function_clause,[{client_handler,terminate,[{function_clause,[{client_handler,handle_info,[{tcp_closed,#Port<0.90>},{noreply,{client_state,<0.28.0>,undefined,starting,{client_info,<0.28.0>,<0.29.0>,#Port<0.90>},undefined,undefined}}]},{gen_server,handle_msg,5},{proc_lib,init_p,5}]},{noreply,{client_state,<0.28.0>,undefined,starting,{client_info,<0.28.0>,<0.29.0>,#Port<0.90>},undefined,undefined}}]},{gen_server,terminate,6},{proc_lib,init_p,5}]},{gen_server,call,[<0.29.0>,irc_accept_clients,infinity]}}}



---------------------------

At point 2; the following server code gets launched.

	io:format("trace: lib:handle_call accept_clients. [~p]~n", [AppHandler]),
	ClientSock = server_accept(ServSock),
	io:format("trace: [!!] lib:handle_call client-socket: [~p]~n", [ClientSock]),
	ClientInfo = #client_info{app_handler=AppHandler,serv_lib=self(),
							  client_sock=ClientSock},
	{ ok, ClientServ } = client_handler:start_link(ClientInfo),
	gen_tcp:controlling_process(ClientSock, ClientServ),
	inet:setopts(ClientSock, [{packet, 0}, binary,
							  {nodelay, true},{active, true}]),
	{reply, ok, State};

--------
This is my code for handling the client connection.

start_link(Client) ->
    gen_server:start_link(?MODULE, [Client], []).

init([Client]) ->
	AppHandler = Client#client_info.app_handler,
	io:format("trace: client_handler:init. handler:[~p]~n", [AppHandler]),
	{ok, #client_state{app_handler=AppHandler,
					   connection_timeout=undefined,
					   client=Client,
					   state=starting}}.

handle_call(get_cur_state, _From, #client_state{} = State) ->
	% Generic method to get the current state.
	io:format("trace: lib:handle_call:get_cur_state~n"),
	{reply, {ok, State}, State}.

terminate(_Reason, #client_state{client=Client}) ->
    io:format("trace: client:handler:terminate reason:[~p]~n", [_Reason]),
    ok;
terminate(normal, #client_state{client=Client}) ->
    io:format("trace: client:handler:terminate.normal~n"),
    ok;
terminate(shutdown, #client_state{client=Client}) ->
    io:format("trace: client:handler:terminate.shutdown~n"),
    ok.

handle_info({tcp, Sock, Data}, State) ->	
    inet:setopts(Sock, [{active, once}]),
	io:format("trace: lib:info.tcp data [~p]~n", [Data]),
 	{Prefix, Command, Args} =
 		try data_lib:scan_string(Data)
 		catch
 			_:_ ->
 				io:format("ERROR: error attempting to parse input command~n"),
 				{"", "SYS_INVALID", ""}
 		end,	
 	% Invoke the client data handler to process incoming messages.
 	HandleState=client_handle_data(State, {Prefix, Command, Args}),
    {noreply, {noreply, State}};
handle_info({tcp_closed, Sock}, #client_state{app_handler=AppHandler}
= State) ->
	io:format("trace: lib:info.tcp_closed~n"),
	inet:setopts(Sock, [{active, once}]),
	AppHandler ! {connection_closed},
    {noreply, State#client_state{state=disconn}};
handle_info({tcp_error, Sock, Reason}, State) ->
	io:format("trace: lib:info.tcp_error~n"),
    inet:setopts(Sock, [{active, once}]),
    {noreply, State#client_state{state=disconn}}.



-- 
Berlin Brown
http://botspiritcompany.com/botlist/spring/help/about.html



More information about the erlang-questions mailing list