gen_server not getting messages after httpc call - erlang

I have one process which sends a pause message to a gen_server like so:
Results = [gen_server:cast(Child, pause) ||
{Id, Child, _Type, _Modules} <- supervisor:which_children(?SERVER),
?IGNORE(Id) == false],
In my gen_server, I catch these messages in my handle_cast as follows:
handle_cast(pause, #state{task=#task{server=Serv,
service=Srv,
description=Desc}}=State) ->
lager:info("Suspending ~s, ~s, ~s.",[Serv, Srv, Desc]),
{noreply, State#state{suspended=true}};
handle_cast(Msg, State) ->
lager:error("Url Poller received unexpected cast message: ~p",[Msg]),
{noreply, State}.
What's really strange is that fairly frequently one of my gen_servers doesn't seem to receive the pause message -- I get no lager message and the process in question will not respond to subsequent attempts to pause (or resume).
Any ideas about what might be going on?
The gen_server is very simple, it uses erlang:send_after/3 to send itself a "poll" message. Upon receiving this poll message, if not paused, it hits a url and saves the response to an ETS and fires off another erlang:send_after/3 to poll again after an appropriate interval. If its paused, it simply fires off another erlang:send_after?3
All pause does is set the state to paused = true
Using observer, the stuck process shows that the current function is httpc:handle_answer and that the message queue is backing up
Sate Tab: Information "Timed out"
Tip "system messages are probably not treated by this process"
the top of the stack trace shows
httpc:handle_answer httpc.erl:636

I picked the code of httpc:handle_answer from github erlang otp inets http client:
(Note: it is not the same version as yours since the function goes from line 616 to 631)
handle_answer(RequestId, false, _) ->
{ok, RequestId};
handle_answer(RequestId, true, Options) ->
receive
{http, {RequestId, saved_to_file}} ->
?hcrt("received saved-to-file", [{request_id, RequestId}]),
{ok, saved_to_file};
{http, {RequestId, {_,_,_} = Result}} ->
?hcrt("received answer", [{request_id, RequestId},
{result, Result}]),
return_answer(Options, Result);
{http, {RequestId, {error, Reason}}} ->
?hcrt("received error", [{request_id, RequestId},
{reason, Reason}]),
{error, Reason}
end.
So the process is waiting for a message (coming after a call to httpc_manager:request(Request, profile_name(Profile) which has returned {ok, RequestId}), and this message does not come or it has a wrong format. Can you check the values of the parameters and the message queue?

headers which contained value other than string caused the httpc_handler exited. But after that, the caller hung at the 'receive' in httpc:handle_answer/3 forever since no message was sent to the caller.
you can test with this
Request1= {"http://www.google.com",[{"cookie",undefined}, {"test",123}],"application/x-www-form-urlencoded; charset=utf-8", <<"">>}.
httpc:request(post, Request1, [{timeout,1000}], []).

Related

gen_server , a server can’t call its own API functions?

When I read Erlang OTP Action book, I found this reminder on page 117:
With your RPC server, you can try calling any function exported from any module available on the server side, except one: your own tr_server:get_count/0. In general, a server can’t call its own API functions. Suppose you make a synchronous call to the same server from within one of the callback functions: for example, if handle_info/2 tries to use the get_count/0 API function. It will then perform a gen_server:call(...) to itself. But that request will be queued up until after the current call to handle_info/2 has finished, resulting in a circular wait—the server is deadlocked.
But I looked at the tr_server sample code :
get_count() ->
gen_server:call(?SERVER, get_count).
stop() ->
gen_server:cast(?SERVER, stop).
handle_info({tcp, Socket, RawData}, State) ->
do_rpc(Socket, RawData),
RequestCount = State#state.request_count,
{noreply, State#state{request_count = RequestCount + 1}};
......
do_rpc(Socket, RawData) ->
try
{M, F, A} = split_out_mfa(RawData),
Result = apply(M, F, A), % tr_server process -> handle_info -> do_rpc ->call & cast
gen_tcp:send(Socket, io_lib:fwrite("~p~n", [Result]))
catch
_Class:Err ->
gen_tcp:send(Socket, io_lib:fwrite("~p~n", [Err]))
end.
I found the examples and cautions in the book inconsistent , the gen_server:call and gen_server:cast by tr_server process ownself.
Am I misinterpreting this?
Calling gen_server:cast from within the server process is fine, because it is asynchronous: it adds the message to the mailbox of the process and then continues, returning ok. Only gen_server:call has this problem, because it makes the process wait for an answer from itself.

How do I update my PID on a timer?

I am trying to update my process's state on a 10 second timer.
-define(INTERVAL, 3000).
start_link() ->
gen_server:start_link(?MODULE, [], []).
action(Pid, Action) ->
gen_server:call(Pid, Action).
init([]) ->
erlang:send_after(?INTERVAL, self(), trigger),
{ok, temple:new()}.
what I want to do is call this
handle_call({fight}, _From, Temple) ->
NewTemple = temple:fight(Temple),
{reply, NewTemple, NewTemple};
So I try
handle_info(trigger, _State) ->
land:action(self(), {fight}),
erlang:send_after(?INTERVAL, self(), trigger);
but I get
=ERROR REPORT==== 4-Dec-2016::19:00:35 ===
** Generic server <0.400.0> terminating
** Last message in was trigger
** When Server state == {{dict,0,16,16,8,80,48,
{[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],
[]},
{{[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],
[]}}},
[]}
** Reason for termination ==
** {function_clause,[{land,terminate,
[{timeout,{gen_server,call,[<0.400.0>,{fight}]}},
{{dict,0,16,16,8,80,48,
{[],[],[],[],[],[],[],[],[],[],[],[],[],[],
[],[]},
{{[],[],[],[],[],[],[],[],[],[],[],[],[],
[],[],[]}}},
[]}],
[{file,"src/land.erl"},{line,47}]}
It appears that with land:action(self(), {fight}), you're attempting to make a call to the same gen_server in which you're currently handling the trigger message. Two important facts will explain why this can't work:
A call always waits for the result to be returned.
A gen_server is a process, and a process can handle only one message at a time.
In handling the trigger message, you're saying to call back to yourself and wait for yourself to process the {fight} message. Since you're in the middle of handling the trigger message, though, you'll never get to the {fight} message. You're effectively in a deadlock with yourself. That's why you're getting a timeout.
P.S. Posting an SSCCE is far more likely to get you good answers.
The error message means that there is no terminate clause in the land server module, you should have a warning when you compile the land server module.
The terminate clause is called because a timeout occurs during the gen_server call with the parameters (Pid = <0.400.0>, Message = {fight}), which was called on line land:action(self(), {fight}),. A call to a gen_server must be completed within a maximum time, by default 5000ms, You have to reduce the time spent in the fight action.
Note that it is not a good idea to increase the server timeout since a gen_server call is blocking: during the execution of a gen_server call no new message can be handled, and in your example , it is also blocking the execution of the handle_info(trigger, _State) code.
Last point, the clause handle_info(trigger, _State) should return a tuple of the form {noreply,NewState} while the last line erlang:send_after(?INTERVAL, self(), trigger); returns a timer reference, you have to modify this line.

send message to gen_server before init

I am new to erlang, I having following code:
-module (test_srv).
-behaviour (gen_server).
-export ([start_link/0, init/1, handle_info/2]).
start_link() ->
gen_server:start_link(?MODULE, [], []).
init([]) ->
self() ! asdasd,
{ok, new_state}.
handle_info(Msg, State) ->
io:format("server got ~p , now state is ~p~n", [Msg, State]),
{noreply, State}.
I test in erl shell:
1> {_, P} = test_srv:start_link().
server got asdasd , now state is new_state
The problem is, When send a message to server when the server is not initialised and not readly, how dose gen_server handle the message? I have following guesses:
gen_server handle the message immediately, and send the message to handle_info callback, but will lose initialised state in init callback
gen_server store the message if not server initialised, and send message after server initialised.
I wanna to know how erlang or gen_server handle this problem? what is the principle of handle message?
I'm guessing by server is not initialised you mean the rest of the init function being executed. In that case your second guess is correct. It's guaranteed that the handle_info will be executed after init has returned. Since the gen_server is a single process, and you're already executing init, the messages sent to itself from init will only be processed by gen_server after init has finished executing.

Unsupervised gen_server doesn't call terminate when it receives exit signal

gen_server documentation on Module:terminate callback says:
Even if the gen_server process is not part of a supervision tree, this
function is called if it receives an 'EXIT' message from its parent.
Reason is the same as in the 'EXIT' message.
Here is my handle_info and terminate function:
handle_info(UnknownMessage, State) ->
io:format("Got unknown message: ~p~n", [UnknownMessage]),
{noreply, State}.
terminate(Reason, State) ->
io:format("Terminating with reason: ~p~n", [Reason]).
I start this server using gen_server:start. I assume when I call erlang:exit(Pid, fuckoff), it should call terminate callback function. But it shows:
Got unknown message: {'EXIT',<0.33.0>,fuckoff}
Which means it is calling handle_info. But when I call gen_server:stop, everything works as mentioned in documentation. I'm calling my gen_server from shell. Would you please clarify this?
[UPDATE]
Here is source code of decode_msg function inside gen_server. If it receives any 'EXIT' message it should call terminate function:
decode_msg(Msg, Parent, Name, State, Mod, Time, Debug, Hib) ->
case Msg of
{system, From, Req} ->
sys:handle_system_msg(Req, From, Parent, ?MODULE, Debug,
[Name, State, Mod, Time], Hib);
{'EXIT', Parent, Reason} ->
terminate(Reason, Name, Msg, Mod, State, Debug);
_Msg when Debug =:= [] ->
handle_msg(Msg, Parent, Name, State, Mod);
_Msg ->
Debug1 = sys:handle_debug(Debug, fun print_event/3,
Name, {in, Msg}),
handle_msg(Msg, Parent, Name, State, Mod, Debug1)
end.
In my case it doesn't call terminate function.
[UPDATE]
When I start gen_server using gen_server:start_link(), sending an exit signal using erlang:exit(Pid, Reason) will result in calling terminate call back function which is an expected behaviour. It seems there is a difference in interpreting an exit signal whether a process is linked to its parent or not.
Short answer:
If you call the exit/2 function from inside the gen_server actor, it behaves as expected based on the documentation and the terminate/2 callback will be called.
Long answer:
When you send the exit message from the shell, the Parent value of exit tuple is set to the shell process id, on the other hand when you start the gen_server process form shell its Parent value is set to its own process id, not the shell process id, therefore when it gets the exit message it doesn't match the second clause of the receive block in decode_msg/8 function so the terminate/6 function is not called and finally the next clause is matched which is calling handle_msg/5 function.
Recommendation:
For getting the terminate/3 callback called even by sending an exit message to the gen_server process, you can trap the exit message in handle_info/2 and then return with stop tuple as follows:
init([]) ->
process_flag(trap_exit, true),
{ok, #state{}}.
handle_info({'EXIT', _From, Reason}, State) ->
io:format("Got exit message: ~p~n", []),
{stop, Reason, State}.
terminate(Reason, State) ->
io:format("Terminating with reason: ~p~n", [Reason]),
%% do cleanup ...
ok.
When you start your gen_server, its a simple process, so, erlang:exit/1 or erlang:exit/2 work as expected.
If Pid is not trapping exits, Pid itself exits with exit reason Reason.
If Pid is trapping exits, the exit signal is transformed into a message {'EXIT', From, Reason} and delivered to the message queue of Pid.
So, currently your code trap 'EXIT' signal because this one is send like any other message into the mailbox and match handle_info/2 wildcard pattern.
If you want more information about that, you can read gen_server source code and see how it works. You can also find your problem described in this code.

What happens if you do not call the function again at the end of a receive block? - Erlang

An example of this would be:
myFunction()
receive
msg1 -> io:format("Message 1!~n"),
self() ! msg1,
myFunction();
msg2 -> io:format("Message 2!~n")
end.
I learnt to do my messages like msg1; but recently I made an error and compiled my code similar to msg2. When msg2 occurs, what happens afterwards? Does the process just sit at that same receive after msg2 and wait for other messages?
Why don't you try it yourself?
If you don't call the function after receiving msg2, then there is nothing more to execute and your process will quit.
Does the process just sit at that same receive after msg2 and wait for other messages?
No. You need to call the function again. The recursion creates a loop.
When msg2 occurs, what happens afterwards?
Message 2!\n is printed and myFunction/0's code is no longer executed, and if the current process has nothing more to do it exits.
if you don't call the function again at the end of a receive block, the process will die.(if you case, if you send msg2 to the process), but if you send other message(except for msg1 and msg2), the process will wait, and the messages are stored in the process's message queue.
-module(wy).
-compile(export_all).
myFunction() ->
receive
msg1 ->
io:format("Message 1!~n"),
self() ! msg1,
myFunction();
msg2 ->
io:format("Message 2!~n")
end.
parent() ->
Pid = spawn(fun myFunction/0),
register(myFunction, Pid),
erlang:monitor(process, Pid),
receive
Res -> io:format("Receive ~p~n", [Res])
end.
main() ->
spawn(fun() -> parent() end).
first you need execute wy:main().
(1) if you execute myFunction ! msg22., you can find the process myFunction is still alive, and use this command erlang:process_info(whereis(myFunction), messages)., you can find the message msg22 is stored in the message queue.
(2) if you execute myFunction ! msg2., you can get this output
Message 2!
Receive {'DOWN',#Ref<0.0.0.108>,process,<0.48.0>,normal}
msg2
from this output you can know the process myFunction is died.
(3) if you execute myFunction ! msg1, the process will go into endless loop。
The other answers are almost correct. If you don't do a recursive call after receiving msg2 then the function will end and you will go back to the caller of myFunction/0. It will then depend on the caller what happens. If this is the last thing to do in the process then the process will terminate with reason normal, otherwise it will continue processing.
The thing to remember is that each call to receive will just process one message so if you want to keep processing messages then you must do repeated calls to receive. Hence the recursion in myFunction.

Resources