<div dir="ltr"><div>the so called controller is a simple gen_server and is atarted by a supervisor when application starts<br><br></div>supervisor snippet:<br>init([]) -><br>    [{port, Port}] = ets:lookup(config, port),<br>    [{listen, IPv4}] = ets:lookup(config, listen),<br>    <br>    MpsConn = {mps_controller,{mps_controller, start_link, [Port, IPv4]},<br>             temporary, 5000, worker, [mps_controller]},<br><br>     {ok,{{one_for_all, 3, 10}, [MpsConn]}}.<br><br><div><br></div><div>and controller:<br></div><div><br>-module(mps_controller).<br>-behaviour(gen_server).<br><br>-include("../include/mps.hrl").<br><br>-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).<br><br>%% ====================================================================<br>%% API functions<br>%% ====================================================================<br>-export([start_link/2, stop/0]).<br><br>%% ====================================================================<br>%% Behavioural functions<br>%% ====================================================================<br>%% -record(state, {}).<br><br>start_link(Port, Ip) -><br>       gen_server:start_link(?MODULE, [Port, Ip] []).<br><br>stop() -><br>       gen_server:call(?MODULE, stop).<br><br>%% init/1<br>%% ====================================================================<br>%% @doc <a href="<a href="http://www.erlang.org/doc/man/gen_server.html#Module:init-1">http://www.erlang.org/doc/man/gen_server.html#Module:init-1</a>">gen_server:init/1</a><br>-spec init(Args :: term()) -> Result when<br>    Result :: {ok, State}<br>            | {ok, State, Timeout}<br>            | {ok, State, hibernate}<br>            | {stop, Reason :: term()}<br>            | ignore,<br>    State :: term(),<br>    Timeout :: non_neg_integer() | infinity.<br>%% ====================================================================<br>init([Port, Ip]) -><br>        process_flag(trap_exit, true),<br>        <br>        {ok, Sock} = gen_udp:open(Port, [binary,<br>                            {active, false},<br>                             {reuseaddr, true},<br>                            {ip, Ip}<br>        ]),<br>        <br>        {ok, #udp_conn_state{sock = Sock}, 0}.<br><br>%% handle_call/3<br>%% ====================================================================<br>%% @doc <a href="<a href="http://www.erlang.org/doc/man/gen_server.html#Module:handle_call-3">http://www.erlang.org/doc/man/gen_server.html#Module:handle_call-3</a>">gen_server:handle_call/3</a><br>-spec handle_call(Request :: term(), From :: {pid(), Tag :: term()}, State :: term()) -> Result when<br>    Result :: {reply, Reply, NewState}<br>            | {reply, Reply, NewState, Timeout}<br>            | {reply, Reply, NewState, hibernate}<br>            | {noreply, NewState}<br>            | {noreply, NewState, Timeout}<br>            | {noreply, NewState, hibernate}<br>            | {stop, Reason, Reply, NewState}<br>            | {stop, Reason, NewState},<br>    Reply :: term(),<br>    NewState :: term(),<br>    Timeout :: non_neg_integer() | infinity,<br>    Reason :: term().<br>%% ====================================================================<br>handle_call(Request, From, State) -><br>    Reply = ok,<br>    {reply, Reply, State}.<br><br><br>%% handle_cast/2<br>%% ====================================================================<br>%% @doc <a href="<a href="http://www.erlang.org/doc/man/gen_server.html#Module:handle_cast-2">http://www.erlang.org/doc/man/gen_server.html#Module:handle_cast-2</a>">gen_server:handle_cast/2</a><br>-spec handle_cast(Request :: term(), State :: term()) -> Result when<br>    Result :: {noreply, NewState}<br>            | {noreply, NewState, Timeout}<br>            | {noreply, NewState, hibernate}<br>            | {stop, Reason :: term(), NewState},<br>    NewState :: term(),<br>    Timeout :: non_neg_integer() | infinity.<br>%% ====================================================================<br>handle_cast(Msg, State) -><br>    {noreply, State}.<br><br>%% handle_info/2<br>%% ====================================================================<br>%% @doc <a href="<a href="http://www.erlang.org/doc/man/gen_server.html#Module:handle_info-2">http://www.erlang.org/doc/man/gen_server.html#Module:handle_info-2</a>">gen_server:handle_info/2</a><br>-spec handle_info(Info :: timeout | term(), State :: term()) -> Result when<br>    Result :: {noreply, NewState}<br>            | {noreply, NewState, Timeout}<br>            | {noreply, NewState, hibernate}<br>            | {stop, Reason :: term(), NewState},<br>    NewState :: term(),<br>    Timeout :: non_neg_integer() | infinity.<br>%% ====================================================================<br><br>handle_info({udp, Socket, Host, Port, Bin}, State) -><br>     {noreply, State, 1};<br><br>handle_info(timeout, #udp_conn_state{sock = Sock} = State) -><br>    inet:setopts(Sock, [{active, once}]),<br>    {noreply, State};<br><br>handle_info(Info, State) -><br>    {noreply, State}.<br><br>%% terminate/2<br>%% ====================================================================<br>%% @doc <a href="<a href="http://www.erlang.org/doc/man/gen_server.html#Module:terminate-2">http://www.erlang.org/doc/man/gen_server.html#Module:terminate-2</a>">gen_server:terminate/2</a><br>-spec terminate(Reason, State :: term()) -> Any :: term() when<br>    Reason :: normal<br>            | shutdown<br>            | {shutdown, term()}<br>            | term().<br>%% ====================================================================<br>terminate(Reason, State) -><br>    ok.<br><br><br>%% code_change/3<br>%% ====================================================================<br>%% @doc <a href="<a href="http://www.erlang.org/doc/man/gen_server.html#Module:code_change-3">http://www.erlang.org/doc/man/gen_server.html#Module:code_change-3</a>">gen_server:code_change/3</a><br>-spec code_change(OldVsn, State :: term(), Extra :: term()) -> Result when<br>    Result :: {ok, NewState :: term()} | {error, Reason :: term()},<br>    OldVsn :: Vsn | {down, Vsn},<br>    Vsn :: term().<br>%% ====================================================================<br>code_change(OldVsn, State, Extra) -><br>    {ok, State}.<br><br><br><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Dec 9, 2015 at 4:27 PM, Fred Hebert <span dir="ltr"><<a href="mailto:mononcqc@ferd.ca" target="_blank">mononcqc@ferd.ca</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">On 12/09, Bogdan Andu wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
handle_info({udp, Socket, Host, Port, Bin}, State)  -><br>
   {noreply, State};<br>
<br>
In a few minutes the memory allocated to binary increases to ~ 500MB<br>
by running the command:<br>
<br>
fmpeg -f lavfi -i aevalsrc="sin(40*2*PI*t)" -ar 8000 -f mulaw -f rtp rtp://<br>
<a href="http://10.10.13.104:5004" rel="noreferrer" target="_blank">10.10.13.104:5004</a><br>
<br>
It seems that the Bins are accumulated in the process memory area, an never<br>
are deallocated<br>
unless the process is killed, which is not an option.<br>
</blockquote>
<br></span>
So there's two ways about that. If the size of each binary is > 64 bits, then the binary is moved to a global shared heap, and is only collected once no process at all has a reference to it anymore.<br>
<br>
This takes a few forms:<br>
<br>
1. either the process receiving the data and passing it on holds on to it inadvertently by not garbage-collecting<br>
2. the processes the messages would be forwarded to are keeping a copy.<br>
3. the process isn't keeping up<br>
<br>
In this case, it would be weird for it to be blameable on 2) and 3) since the snippet above does not forward data, and because "not keeping up" would affect both forms the same (the following one, I mean:)<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">
If I change the clause to:<br>
handle_info({udp1, Socket, Host, Port, Bin}, State) -><br>
<br></span><span class="">
So as long as the process receives the packet, this is accumulated in<br>
binary memory are<br>
and never deallocated.<br>
</span></blockquote>
<br>
So the interesting bit there is are you sure the memory isn't just going elsewhere? That you're doing nothing with the process? Not matching on the message does not mean the message isn't read. Any receive operation (or most of them, as far as I can tell) work by taking the messages in the mailbox, copying them to the process heap, potentially running a GC, and then getting the message.<br>
<br>
Simply not matching the message does not take it out of the mailbox; in fact I would expect bigger leaks with that clause, unless you have a second one that broadly matches on all messages and discards them.<br>
<br>
Then the problem would point at being about what you do with the message.<br>
<br>
The thing I would check is:<br>
a) are you keeping more references than you think in what you do, or is <br><span class="">
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
handle_info({udp, Socket, Host, Port, Bin}, State)  -><br>
   {noreply, State};<br>
</blockquote>
<br></span>
really the full clause?<br>
<br>
Another option can be to return {noreply, State, hibernate} from time to time, which will force a full GC and recompaction of the process memory.  If the memory isn't shed away after that, then you know it's being either still referenced by the process, or has another process referencing it.<br>
<br>
Regards,<br>
Fred.<br>
<br>
<br>
</blockquote></div><br></div>