[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