[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