Triggering the update message in Erlang hot code reload feature - erlang

I am trying the hot code feature of erlang following the guide from LYAE but i do not understand how to make the update message to get triggered.
I have a module which runs a method that is upgradeable:
Module
-module(upgrade).
-export([main/1,upgrade/1,init/1,init_link/1]).
-record(state,{ version=0,comments=""}).
init(State)->
spawn(?MODULE,main,[State]).
main(State)->
receive
update->
NewState=?MODULE:upgrade(State),
if NewState#state.version>3 -> exit("Max Version Reached") end,
?MODULE:main(NewState);
SomeMessage->
main(State)
end.
upgrade(State=#state{version=Version,comments=Comments})->
Comm=case Version rem 2 of
0 -> "Even version";
_ -> "Uneven version"
end,
#state{version=Version+1,comments=Comm}.
Shell
>c(upgrade).
>rr(upgrade,state).
>U=upgrade:init(#state{version=0,comments="initial"}).
>Monitor=monitor(process,U).
> ......to something to trigger the update message
> flush(). % see the exit message reason
I do not understand how can i perform a hot code reload in order to trigger the update message.
I want when i use flush to get the exit reason from my main method.

The process expects to get the atom update as a message. Since you have the pid of the process in the variable U, you can send the message like this:
U ! update.
Note that the strings Even version and Uneven version are only kept in the state, never printed, so you won't see those. The only thing you'll see is the exit message, after sending update four times and calling flush().

Related

What is the detail of the Erlang select receive mechanism?

I have read an article about the Erlang select receive mechanism at the end of the article, there is a conclusion: "messages are moved from the mailbox to the save queue and then back to the mailbox after the matching message arrives". I have tried the example shown in the article, but I couldn't get the same result. Here is my code and my erlang/otp version is 21.
shell1:
(aaa#HW0003727)1> register(shell, self()).
true
(aaa#HW0003727)2> shell ! c, shell ! d.
d
(aaa#HW0003727)3> process_info(whereis(shell),messages).
{messages,[c,d]}.
(aaa#HW0003727)4> receive a -> 1; b -> 2 end.
shell2:
(aaa#HW0003727)1> process_info(whereis(shell),messages).
{messages,[c,d]}
(aaa#HW0003727)2> process_info(whereis(shell)).
[{registered_name,shell},
{current_function,{prim_eval,'receive',2}},
{initial_call,{erlang,apply,2}},
{status,waiting},
{message_queue_len,2},
{links,[<0.113.0>]},
{dictionary,[]},
{trap_exit,false},
{error_handler,error_handler},
{priority,normal},
{group_leader,<0.112.0>},
{total_heap_size,4212},
{heap_size,1598},
{stack_size,30},
{reductions,13906},
{garbage_collection,[{max_heap_size,#{error_logger => true,kill => true,size => 0}},
{min_bin_vheap_size,46422},
{min_heap_size,233},
{fullsweep_after,65535},
{minor_gcs,1}]},
{suspending,[]}]
The article.
This strange behaviour with the visible state of a "save queue" was only true in the interpreted code running in the shell, not in regular compiled modules. In the actual C implementation of receive, there is only one queue with a pointer to keep track of which ones have been scanned so far, and process_info does not show an empty queue during a real receive. The behaviour of the interpreted code was fixed back in R16B01, so nowadays there is no visible difference: https://github.com/erlang/otp/commit/acb8ef5d18cc3976bf580a8e6925cb5641acd401

How to use ssh_connection:exec in Erlang?

This is an interesting situation, focused on the behavior of erlang ssh modules. I had spent a few hours troubleshooting a problem that turned out to reveal that the Erlang ssh_connection *exec/4* function operates asynchronously.
If you issue the ssh_connection:exec/4 function to run a script that takes several seconds to complete, and then in your erlang program you close the ssh connection, the script execution will terminate. My expectation was that the ssh_connection:exec would be synchronous rather than asynchronous.
Because the time to complete the remote script invoked by ssh_connection:exec is unknown, I chose to not issue the closure ssh:close(). I would like to understand the consequences of that:
Will the gc clear it at some point ?
Will it stay open for good during the whole node existence ?
Is there a way to make the ssh_connection:exec synchronous, as I would believe it should be.
Here is an example of the test erl program that I used to verify this issue. As a script you can run a simple sleep 10 (sleep 10 seconds) to emulate a slow running program.
-module(testssh).
-export([test/5]).
test (ServerName, Port, Command, User, Password) ->
crypto:start(),
ssh:start(),
{ok, SshConnectionRef} = ssh:connect(ServerName, Port, [ {user, User}, {password, Password} , {silently_accept_hosts, true} ], 60000 ),
{ok, SshConnectionChannelRef} = ssh_connection:session_channel(SshConnectionRef, 60000),
Status = ssh_connection:exec(SshConnectionRef, SshConnectionChannelRef, Command, 60000),
ssh:close(SshConnectionRef).
Remote script:
#!/bin/sh
sleep 10
I never had to use the ssh application myself, but you should be reading something wrong, it is clear in the doc that the result will be delivered as messages to the caller:
[...] the result will be several messages according to the following pattern. Note that the last message will be a channel close message, as the exec request is a one time execution that closes the channel when it is done[...]
See http://www.erlang.org/doc/man/ssh_connection.html#exec-4
So after you call ssh_connection:exec/4 , test with a loop like this:
wait_for_response(ConnectionRef) ->
receive
{ssh_cm, ConnectionRef, Msg} ->
case Msg of
{closed, _ChannelId} ->
io:format("Done");
_ ->
io:format("Got: ~p", [Msg]),
wait_for_response(ConnectionRef)
end
end.
You should receive the command output, and other ssh messages, and finally a 'closed' message that is your signal that the ssh command has properly finished.

Which one should I use exit, error or throw?

Could you tell me when to use throw, exit and error?
1> catch throw ({aaa}).
{aaa}
2> catch exit ({aaa}).
{'EXIT',{aaa}}
3> catch gen_server:call(aaa,{aaa}).
{'EXIT',{noproc,{gen_server,call,[aaa,{aaa}]}}}
4> catch exit("jaj")
{'EXIT',"jaj"}
There are 3 classes which can be caught with a try ... catch: throw, error and exit.
throw is generated using throw/1 and is intended to be used for non-local returns and does not generate an error unless it is not caught (when you get a nocatch error).
error is generated when the system detects an error. You can explicitly generate an error using error/1. The system also includes a stacktrace in the generated error value, for example {badarg,[...]}.
exit is generated using exit/1 and is intended to signal that this process is to die.
The difference between error/1 and exit/1 is not that great, it more about intention which the stacktrace generated by errors enhances.
The difference between them is actually more noticeable when doing catch ...: when throw/1 is used then the catch just returns the thrown value, as is expected from a non-local return; when an error/1 is used then the catch returns {'EXIT',Reason} where Reason contains the stacktrace; while from exit/1 catch also returns {'EXIT',Reason} but Reason only contains the actual exit reason. try ... catch looks like it equates them, but they are/were very different.
[UPDATED]
I glossed over the important difference between throw and error, pointed out by Robert Virding. This edit is just for the record!
throw error is to be used where one would use throw in other languages. An error in a running process has been detected by your code, which signals an exception with error/1. The same process catches it (possibly higher up in the stack), and the error is to be handled within the same process. error always brings with it a stacktrace.
throw is to be used not to signal an error, but just to return a value from a deeply nested function.
Since it unwinds the stack, calling throw returns the thrown value to the place it was caught. As in the case of error, we're catching stuff that was thrown, only what was thrown wasn't an error but rather just a value passed up the stack. This is why throw does not bring with it a stacktrace.
As a contrived example, if we wanted to implement an exists function for lists, (similar to what list:any does) and as an exercise without doing the recursing ourselves, and using just list:foreach, then throw could be used here:
exists(P, List) ->
F = fun(X) ->
case P(X) of
true -> throw(true);
Whatever -> Whatever
end
end,
try lists:foreach(F, List) of
ok -> false
catch
true -> true
end.
A value thrown but not caught is treated as an error: a nocatch exception will be generated.
EXIT is to be signaled by a process when it 'gives up'. The parent process handles the EXIT, while the child process just dies. This is the Erlang let-it-crash philosophy.
So exit/1's EXIT is not to be caught within the same process, but left to the parent. error/1's errors are local to the process - i.e., a matter of what happens and how it is handled by the process itself; throw/1 is used for control flow across the stack.
[UPDATE]
This tutorial explains it well: http://learnyousomeerlang.com/errors-and-exceptions
Note there is also a exit/2 - called with a Pid of a process to send the EXIT to.
exit/1 implies the parent process.
I'm new to Erlang, but here's how I think about what these things are, their differences, what they're used for, etc.:
throw: a condition that should be handled locally (i.e. within the current process). E.g. caller is looking for an element in a collection, but does not know if the collection actually contains such an element; then, the callee could throw if such an element is not present, and the caller detect absence by using try[/of]/catch. If caller neglects to do this, then this gets turned into an nocatch error (explained below).
exit: The current process is done. E.g. it has simply finished (in that case, you'd pass normal, which is treated the the same as the original function returning), or its operation was cancelled (E.g. it normally loops indefinitely but has just received a shut_down message).
error: the process has done something and/or reached a state that the programmer did not take into account (E.g. 1/0), believes is impossible (E.g. case ... of encounters a value that does not match any case), or some precondition is not met (E.g. input is nonempty). In this case, local recovery doesn't make sense. Therefore, neither throw nor exit is appropriate. Since this is unexpected, a stack trace is part of the Reason.
As you can see, the above list is in escalating order:
throw is for sane conditions that the caller is expected to handle. I.e. handling occurs within the current process.
exit is also sane, but should end the current process simply because the process is done.
error is insane. Something happened that can't reasonably be recovered from (usually a bug?), and local recovery would not be appropriate.
vs. other languages:
throw is analogous to the way checked exceptions are used in Java. Whereas, error is used in a manner more analogous to unchecked exceptions. Checked exceptions are exceptions you want the caller to handle. Java requires you to either wrap calls in try/catch or declare that your method throws such exceptions. Whereas, unchecked exceptions generally propagate to the outermost caller.
exit does not have a good analog in more "conventional" languages like Java, C++, Python, JavaScript, Ruby, etc. exit vaguely like an uber-return: instead of returning at the end, you can return from the middle of a function, except you don't just return from the current function, you return from them ALL.
exit Example
serve_good_times() ->
receive
{top_of_the_mornin, Sender} ->
Sender ! and_the_rest_of_the_day_to_yourself;
{you_suck, Sender} ->
Sender ! take_a_chill_pill;
% More cases...
shut_down ->
exit(normal)
end,
serve_good_times()
end
Since serve_good_times calls itself after almost all messages, the programmer has decided that we don't want to repeat that call in every receive case. Therefore, she has put that call after the receive. But then, what if serve_good_times decides to stop calling itself? This is where exit comes to the rescue. Passing normal to exit causes the process to terminate just as though the last function call has returned.
As such, it's generally inappropriate to call exit in a general purpose library, like lists. It's none of the library's business whether the process should end; that should be decided by application code.
What About Abnormal exit?
This matters if another process (the "remote" process) is linked to the "local" process that calls exit (and process_flag(trap_exit, true) was not called): Just like the last function returning, exit(normal) does not cause remote process to exit. But if the local process makes a exit(herp_derp) call, then the remote process also exits with Reason=herp_derp. Of course, if the remote process is linked to yet more processes, they also get exit signal with Reason=herp_derp. Therefore, non-normal exits result in a chain reaction.
Let's take a look at this in action:
1> self().
<0.32.0>
2> spawn_link(fun() -> exit(normal) end).
<0.35.0>
3> self().
<0.32.0>
4>
4>
4> spawn_link(fun() -> exit(abnormal) end).
** exception exit: abnormal
5> self().
<0.39.0>
6>
The first process that we spawned did not cause the shell to exit (we can tell, because self returned the same pid before and after spawn_link). BUT the second process did cause the shell to exit (and the system replaced the shell process with a new one).
Of course, if the remote process uses process_flag(trap_exit, true) then it just gets a message, regardless of whether the local process passes normal or something else to exit. Setting this flag stops the chain reaction.
6> process_flag(trap_exit, true).
false
7> spawn_link(fun() -> exit(normal) end).
<0.43.0>
8> self().
<0.39.0>
9> flush().
Shell got {'EXIT',<0.43.0>,normal}
ok
10>
10>
10> spawn_link(fun() -> exit(abnormal) end).
<0.47.0>
11> self().
<0.39.0>
12> flush().
Shell got {'EXIT',<0.47.0>,abnormal}
Recall that I said that exit(normal) is treated like the original function returning:
13> spawn_link(fun() -> ok end).
<0.51.0>
14> flush().
Shell got {'EXIT',<0.51.0>,normal}
ok
15> self().
<0.39.0>
What do you know: the same thing happened as when exit(normal) was called. Wonderful!

Run a command in erlang with a parameter

I'm trying to write a erlang module for ejabberd and can't quite work out the syntax.
What I'm trying to do is when a user sends a off-line message, run a script I've written.
on_offline(_From, To, _Packet) ->
?INFO_MSG("recieved offline packet to ~p", [To]),
?INFO_MSG("Got offline message", []),
osReturn = os:cmd("/opt/ejabberd-2.1.10/newmods/handleoffline.py " ++ To),
?INFO_MSG("Send to handler and got return ~s", [osReturn]),
none.
However when I run it, I get a few errors, if I have ++ To there I get the error
E(<0.423.0>:ejabberd_hooks:294) : {function_clause,
However even if I run it without the ++ I get another error telling me Bad Match.
All I'd like to do is run handleoffline.py with the first part of the user ID, anyone got any suggestions?
From the little information you have provided and assuming that your functions is being called with the ejabberd offline_message_hook I can at least find a problem.
In
osReturn = os:cmd("/opt/ejabberd-2.1.10/newmods/handleoffline.py " ++ To)
you are trying to use the ++ to concatenate the list you provided with To. But the major problem is that To isn't a string (list), and that generates your error. Your function is in the form of
on_offline(From, To, Packet) -> ok
where
To = From = #jid (see jlib)
one way to correct that would be to use
on_offline(_From, To=#jid{user = User, server=Server}, _Packet) ->
...
OsReturn = os:cmd("/opt/ejabberd-2.1.10/newmods/handleoffline.py " ++ User),
?INFO_MSG("Send to handler and got return ~s", [OsReturn]),
none.
because the field user on #jid is a string.
Edit: another error is that you need to chang osReturn to OsReturn because the first is an atom and will raise an error on your code, like selle pointed out
Edit your question and add more information if you have more problems, or to make this one clearer.

Two quick consecutive calls to wf:insert_bottom end up in the reverse order

Using Nitrogen, the Erlang web framework, I have the following method that receives messages and adds them to the bottom of an html element:
receive_messages() ->
receive
Message ->
io:format("~p received ~p", [self(), Message]),
wf:insert_bottom(messages, [#p{}, #span { text=io_lib:format("~p", [Message]) }])
end,
wf:comet_flush(),
receive_messages().
It is set as the usual way for comet:
wf:comet(fun() -> receive_messages() end)
It receives two messages very quickly:
<0.907.0> received {starting_chat,<0.905.0>}
<0.907.0> received {connected_to,<0.902.0>}
This is what I see in the HTML:
{connected_to, <0.902.0>}
{starting_chat, <0.905.0>}
Somehow, they ended in the reverse order.
I've started adding timer:sleep() calls to this method. With 50 milliseconds, they are in the correct order, with 20 they are not. When they are in the incorrect order they seem to be always in the incorrect order, it seems very deterministic.
Any ideas why? Is this a bug? Any ideas what should I do to get them in the correct order other than sleeping?
Also asked on the mailing list, in case there's more info there.
wf_comet.erl has a "strange" reverse call after applying inner_collect_content. My guess is that inner_collect_content used to be tail-recursive sometime ago.
If you apply the timeout, your messages are collected in different loops, one-by-one, so the order is not reversed anymore.
There seems to be a commit fixing this on another repository:
http://github.com/gersh/nitrogen/commit/a8bfcb23d003e68f7394a0455285beeb0fbf9b09

Resources