<div dir="ltr"><div><div><div><div><div><div><div><div><div>After more tests the basic questions that remains ..<br><br></div>Is there a way to have more than one process be blocked<br></div>in gen_udp:recv/2 call as this seems to not be possible right now.<br><br></div>Sequentially works as expected, but when when I try to spawn another process<br></div>that makes and attempt to execute gen_udp:recv/2 while the first process already does<br>gen_udp:recv/2 , the second process gives elready error. This means that 2 process <br>cannot concurrently do gen_udp:recv/2 .<br><br></div>In scenario with socket {active, once} or {active, true} there is only one process that can<br></div>receive the message from socket (the one that does gen_udp:open/2 ), <br>and for multi-threaded applications this quickly can become a bottleneck.<br></div><div>In this case, however, elready error disappears of course. </div>.<br></div><div>I tried both variants and both have disavantages.<br></div><div><br></div>Is there an idiom for designing a udp concurrent server in Erlang?<br></div><div>So far, it seems impossible.<br></div><div><br></div>/Bogdan<br></div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Dec 8, 2015 at 5:24 PM, Guilherme Andrade <span dir="ltr"><<a href="mailto:g@gandrade.net" target="_blank">g@gandrade.net</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
  
    
  
  <div bgcolor="#FFFFFF" text="#000000">
    Hi,<br>
    <br>
    <div>On 08/12/15 11:18, Bogdan Andu wrote:<br>
    </div>
    <blockquote type="cite">
      <div dir="ltr">
        <div>
          <div>
            <div>
              <div>
                <div>
                  <div>
                    <div>
                      <div>
                        <div>
                          <div>[...]<span class=""><br>
                            <br>
                                MpsConn = {mps_conn_fsm,{mps_conn_fsm,
                            start_link, [Sock, SslRecvTimeout, false]},<br>
                                        temporary, 5000, worker,
                            [mps_conn_fsm]},<br>
                                <br>
                                {ok, {{simple_one_for_one, 0, 1},
                            [MpsConn]}}.<br>
                          </span></div>
                        </div>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </blockquote>
    [...]<span class=""><br>
    <blockquote type="cite">
      <div dir="ltr">
        <div>
          <div>
            <div>
              <div>
                <div>
                  <div>
                    <div>
                      <div>
                        <div>
                          <div><br>
                          </div>
                          <a href="mailto:mps_dbg@10.10.13.104" target="_blank">mps_dbg@10.10.13.104</a>)1>
                          <br>
                        </div>
                        (<a href="mailto:mps_dbg@10.10.13.104" target="_blank">mps_dbg@10.10.13.104</a>)1>
                        mps_conn_sup:start_child().<br>
                        {ok,<0.62.0>}<br>
                        (<a href="mailto:mps_dbg@10.10.13.104" target="_blank">mps_dbg@10.10.13.104</a>)2>
                        mps_conn_sup:start_child().<br>
                        {ok,<0.64.0>}<br>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </blockquote>
    <br></span>
    Here is the culprit: you're binding the socket only *once* in the
    supervisor[1], which will be its controlling process, and then
    launching two workers which will try both to read from the same
    socket (which they cannot do because they don't control it) and then
    close it (which, if execution were to even reach that point,
    wouldn't also be what I imagine you most likely intend because you
    would end up closing the same socket twice.)<br>
    <br>
    One solution is to remove the socket from the child spec and move
    the socket binding to the worker code.<br>
    <br>
    In any case, if it were me, I would first try to have a single
    binding process which receives the datagrams and launches workers,
    and avoid overload by combining the {active, N}[2] flow with
    whichever backpressure metric your system would signal; there's no
    particular advantage to having multiple bindings over the same port
    - you won't really end up processing multiple flows at once as if
    they were multiple gen_tcp accepted sockets.<br>
    <br>
    On a final note, I would also advise against executing potentially
    blocking operations on OTP processes' init/1 and make it
    asynchronous instead (e.g. by casting an initialisation request to
    itself) or you'll risk choking up the supervision tree.<br>
    <br>
    <br>
    [1]: <a href="http://www.erlang.org/doc/man/supervisor.html#id242517" target="_blank">http://www.erlang.org/doc/man/supervisor.html#id242517</a><br>
    [2]: <a href="http://www.erlang.org/doc/man/inet.html#setopts-2" target="_blank">http://www.erlang.org/doc/man/inet.html#setopts-2</a><span class="HOEnZb"><font color="#888888">
    <pre cols="72">-- 
Guilherme

<a href="http://www.gandrade.net/" target="_blank">http://www.gandrade.net/</a>
PGP: 0x602B2AD8 / B348 C976 CCE1 A02A 017E 4649 7A6E B621 602B 2AD8
</pre>
  </font></span></div>

</blockquote></div><br></div>