[erlang-questions] UDP socket - ealready ERROR
Bogdan Andu
bog495@REDACTED
Wed Dec 9 09:21:32 CET 2015
After more tests the basic questions that remains ..
Is there a way to have more than one process be blocked
in gen_udp:recv/2 call as this seems to not be possible,
probably because the way udp sockets work.
Sequentially works as expected, but when when I try to spawn another process
that makes and attempt to execute gen_udp:recv/2 while the first process
already does
gen_udp:recv/2 , the second process gives elready error. This means that 2
process
cannot concurrently do gen_udp:recv/2 .
In scenario with socket {active, once} or {active, true} there is only one
process that can
receive the message from socket (the one that does gen_udp:open/2 ),
and for multi-threaded applications this quickly can become a bottleneck.
In this case, however, elready error disappears of course.
.
I tried both variants and both have disavantages.
Is there an idiom for designing a udp concurrent server in Erlang?
So far, it seems impossible.
On Tue, Dec 8, 2015 at 1:18 PM, Bogdan Andu <bog495@REDACTED> wrote:
> Hi,
>
> I try to build a concurrent UDP server in Erlang,
>
> The socket is opened in a supervisor like this:
> init([]) ->
> %%xpp_config_lib:reload_config_file(),
> [{port, Port}] = ets:lookup(config, port),
> [{listen, IPv4}] = ets:lookup(config, listen),
>
> %% for worker
> [{ssl_recv_timeout, SslRecvTimeout}] = ets:lookup(config,
> ssl_recv_timeout),
>
>
> {ok, Sock} = gen_udp:open(Port, [binary,
> {active, false},
> {reuseaddr, true},
> {ip, IPv4},
> {mode, binary}
> ]),
>
>
> MpsConn = {mps_conn_fsm,{mps_conn_fsm, start_link, [Sock,
> SslRecvTimeout, false]},
> temporary, 5000, worker, [mps_conn_fsm]},
>
> {ok, {{simple_one_for_one, 0, 1}, [MpsConn]}}.
>
> and in worker I have:
>
>
> init([Sock, SslRecvTimeout, Inet6]) ->
> process_flag(trap_exit, true),
>
> {ok, recv_pckt, #ssl_conn_state{lsock = Sock, ssl_recv_timeout =
> SslRecvTimeout,
> conn_pid = self(), inet6 = Inet6}, 0}.
>
> %% --------------------------------------------------------------------
> %% Func: StateName/2
> %% Returns: {next_state, NextStateName, NextStateData} |
> %% {next_state, NextStateName, NextStateData, Timeout} |
> %% {stop, Reason, NewStateData}
> %% --------------------------------------------------------------------
> recv_pckt(Event, #ssl_conn_state{lsock = ListenSock, inet6 = Inet6,
> ssl_recv_timeout = SslRecvTimeout} =
> StateData) ->
> %% io:format("**epp_login~n", []),
> %% gen_udp:close(ListenSock),
> {ok, {Address, Port, Packet}} = gen_udp:recv(ListenSock, 0,
> SslRecvTimeout),
> io:format("~p~n", [Packet]),
> gen_udp:close(ListenSock),
> {stop, normal, StateData}.
> %% {next_state, recv_pckt, StateData, 0}.
>
> .. and in Erlang shell :
> Erlang/OTP 18 [erts-7.0] [source] [64-bit] [smp:2:2] [async-threads:10]
> [kernel-poll:false]
>
> mps_dbg@REDACTED)1>
> (mps_dbg@REDACTED)1> mps_conn_sup:start_child().
> {ok,<0.62.0>}
> (mps_dbg@REDACTED)2> mps_conn_sup:start_child().
> {ok,<0.64.0>}
>
> =ERROR REPORT==== 8-Dec-2015::13:09:55 ===
> [<0.64.0>]:[2]:TERMINATE:REASON={{badmatch,{error,ealready}},
> [{mps_conn_fsm,recv_pckt,2,
> [{file,
>
> "/home/andu/remote/hp/home/andu/web/mps/src/mps_conn_fsm.erl"},
> {line,80}]},
> {gen_fsm,handle_msg,7,
> [{file,"gen_fsm.erl"},{line,518}]},
> {proc_lib,init_p_do_apply,3,
>
> [{file,"proc_lib.erl"},{line,239}]}]}:undefined
> (mps_dbg@REDACTED)3>
> =ERROR REPORT==== 8-Dec-2015::13:09:55 ===
> ** State machine <0.64.0> terminating
> ** Last event in was timeout
> ** When State == recv_pckt
> ** Data == {ssl_conn_state,#Port<0.1632>,60000,undefined,undefined,
>
> undefined,[],[],<0.64.0>,undefined,undefined,
> undefined,"en",undefined,false,undefined,
> undefined,undefined,undefined,undefined,
> false,<<>>,<<>>,undefined,0}
> ** Reason for termination =
> ** {{badmatch,{error,ealready}},
> [{mps_conn_fsm,recv_pckt,2,
>
> [{file,"/home/andu/remote/hp/home/andu/web/mps/src/mps_conn_fsm.erl"},
> {line,80}]},
> {gen_fsm,handle_msg,7,[{file,"gen_fsm.erl"},{line,518}]},
> {proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,239}]}]}
>
> =CRASH REPORT==== 8-Dec-2015::13:09:55 ===
> crasher:
> initial call: mps_conn_fsm:init/1
> pid: <0.64.0>
> registered_name: []
> exception exit: {{badmatch,{error,ealready}},
> [{mps_conn_fsm,recv_pckt,2,
> [{file,
>
> "/home/andu/remote/hp/home/andu/web/mps/src/mps_conn_fsm.erl"},
> {line,80}]},
>
> {gen_fsm,handle_msg,7,[{file,"gen_fsm.erl"},{line,518}]},
> {proc_lib,init_p_do_apply,3,
> [{file,"proc_lib.erl"},{line,239}]}]}
> in function gen_fsm:terminate/7 (gen_fsm.erl, line 626)
> ancestors: [mps_conn_sup,<0.60.0>,<0.56.0>]
> messages: []
> links: [<0.61.0>]
> dictionary: []
> trap_exit: true
> status: running
> heap_size: 610
> stack_size: 27
> reductions: 295
> neighbours:
>
> =SUPERVISOR REPORT==== 8-Dec-2015::13:09:55 ===
> Supervisor: {local,mps_conn_sup}
> Context: child_terminated
> Reason: {{badmatch,{error,ealready}},
> [{mps_conn_fsm,recv_pckt,2,
> [{file,
>
> "/home/andu/remote/hp/home/andu/web/mps/src/mps_conn_fsm.erl"},
> {line,80}]},
>
> {gen_fsm,handle_msg,7,[{file,"gen_fsm.erl"},{line,518}]},
> {proc_lib,init_p_do_apply,3,
> [{file,"proc_lib.erl"},{line,239}]}]}
> Offender: [{pid,<0.64.0>},
> {id,mps_conn_fsm},
> {mfargs,{mps_conn_fsm,start_link,undefined}},
> {restart_type,temporary},
> {shutdown,5000},
> {child_type,worker}]
>
>
> When I try to start another concurrent worker I get ealready error.
>
> How can be this error avoided.
>
> The option to make socket active introduces a bottleneck as all messages
> are sent to
> controlling process.
>
> Is there any configuration parameter at os kernel level or via inet_dist
> to fix the error?
>
> OS :
> Linux localhost 4.0.4-301.fc22.x86_64 #1 SMP Thu May 21 13:10:33 UTC 2015
> x86_64 x86_64 x86_64 GNU/Linux
>
> Any help very much appreciated,
>
> Bogdan
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20151209/74b5a0f1/attachment.htm>
More information about the erlang-questions
mailing list