This works in my erlang shell:
1> U = default_user_name().
2> crypto:start().
3> crypto:sha(U).
4> crypto:stop().
But when I compile this:
default_pw() ->
U = default_user_name(),
crypto:start(),
crypto:sha(U),
crypto:stop().
And execute it in the erlang shell, I get this:
1> person:default_pw().
** exception error: bad argument
in function port_control/3
called as port_control(crypto_drv04,5,<<"jDoe">>)
in call from crypto:control/2
Two questions:
1) What am I doing wrong?
2) It seems that I need to start and stop the crypto server. But is there a better place to start and stop it in my application?
Many thanks,
LRP
The error you are getting indicates that the crypto application was not started. An easy way to start it is just to add it as a parameter to erl like so:
$ erl -s crypto
I had a look at the current implementation of crypto and the past release notes for erlang and I came to the following conclusions (someone please correct me if I'm wrong):
Erlang releases <14A require crypto to be started prior to calling any functions because the library used a port driver. This makes sense because I got the error you described with 13B04 after not starting crypto.
Erlang releases >=14A don't require crypto to be started as the implementation now uses NIFs. This makes sense because the current implementation of crypto_server.erl is just a gen_server template, and on 14B03 I don't need to start the application in order to make crypto:sha/1 work.
Related
I'm trying to execute a simple erlang program of adding two numbers.
I'm trying to do this in Eclipse on Ubuntu 10.04 LTS.
When i execute this program, I'm getting the error as shown below:
** exception error: undefined function add:addfunc/0
How do i go about solving this error? Thanks in advance.
This program when executed in the erlang shell is working fine. But when it comes to eclipse it's giving me this error. Not this, any program for that matter is giving me the similar error. Guess I would be missing something about the eclipse configuration.
EDIT:
Anyways, This is the sample add program,
-module(add).
-export([addfunc/0]).
addfunc() ->
5 + 6.
This message tells you that module add doesn't have an exported function addfunc/0.
Ensure the function you want to be called has exactly that name, doesn't expect any
parameters, is
exported, the module is
compiled, the search path includes the compiled beam file and that there is no module clashes using code:clash()
Update
It's not clear how erlide (eclipse erlang plug-in you seem to use) compiles and runs a program. Try to compile source using erlc or inside erl shell. That way you'll have much easier controllable environment and you'll better understand what's going on.
I got exactly the same problem -for a tail recursive fibonacci function- below:
-module(math2).
-export([fibonacci/1]).
fibonacci(0) -> 0;
fibonacci(1) -> 1;
fibonacci(M) -> fibonacci(M-1) + fibonacci(M-2).
In the end, had realized that this is a compile-time exception. Then, have opened a new tab on my shell and tried with erlc, instead of erl.
$ erlc math2.erl
Now I am also able to see math2.beam file created.
Called fibonacci with 10:
4> math2:fibonacci(10).
55
and it worked!
I think you have not compiled the code and you are trying to run the program.
In eclipse, using the "Run" icon, trigger the run; which will get you to the erl shell in the console window.
There you do -
cd("C:\Learning_ERL\src").
And you should see output like-
(Learning-ERL#DALAKSHM-MNFSM)7> cd("C:\Learning_ERL\src").
c:/Learning_ERL/src
ok
Then compile the code -
c(add)
you should see something like this on the erl shell-
(Learning-ERL#DALAKSHM-MNFSM)10> c(add).
{ok,add}
Now you should be seeing a new file called - add.beam in the same directory as that of your erl source file - add.erl
add.beam is a bytecode file
Now you should be able to run the program without any error
How do you try to execute your code?
In your editor, right-click and choose "Run as"->"Erlang application". The VM that is launched will have your project loaded automatically and when editing/saving a file it will get reloaded. When launching, a console appears and you can call your code from there.
If it still doesn't work, what message do you get for m(add).?
I had ejabberd 13.12, all works great until I physically moved server machine to another network, then jabber server start encounting crashes. (the same types and details of networks)
CRASH REPORT Process <0.4260.0> with 0 neighbours exited with reason: call to undefined function
ejabberd_socket:get_conn_type({socket_state,gen_tcp,#Port<0.5852>,<0.4259.0>}) in p1_fsm:terminate/7 line 733
2014-01-23 09:34:42.548 [error] <0.330.0> Supervisor ejabberd_c2s_sup had child undefined started with
{ejabberd_c2s,start_link,undefined} at <0.4260.0> exit with reason call to undefined function
ejabberd_socket:get_conn_type({socket_state,gen_tcp,#Port<0.5852>,<0.4259.0>}) in context child_terminated
after machine migration the statuses of users was changed randomly.
I tried reinstall jabber server and I used ejabberd 2.1.13 compiled from scratch - what give me the same errors while using jabber.
function is:
get_conn_type(StateData) ->
case (StateData#state.sockmod):get_sockmod(StateData#state.socket) of
gen_tcp -> c2s;
p1_tls -> c2s_tls;
ezlib ->
case ezlib:get_sockmod((StateData#state.socket)#socket_state.socket) of
gen_tcp -> c2s_compressed;
p1_tls -> c2s_compressed_tls
end;
ejabberd_http_poll -> http_poll;
ejabberd_http_bind -> http_bind;
_ -> unknown
end.
I want understand this function (good pythoner, never erlang) and add hack or pinpoint the issue: is sth ejabberd specific or sth with sockets (but others network tools/services works perfect).
a) how can I insert to that function interactive debugger and get interactive introspection of stack and variables there.
The error message you're seeing says that the get_conn_type function doesn't exist in the ejabberd_socket module. And this is true; in the standard ejabberd distribution, get_conn_type lives in the ejabberd_c2s module.
If you are positive that neither you nor anyone else has modified the sources, then I would check your installation of Erlang. Perhaps it's broken, or you're using different versions to compile and run the code.
I have a process running on node2. Can I register this process using register/2 on node1? Basically I am trying to do this:
register(process_name, spawn_link(node2, module, function, [Arg1, Arg2]))
I get this error:
** exception error: bad argument
in function register/2
called as register(process_name, <5902.92.0>)
When I register a process local to node1, this works perfectly fine. I could not find any documentation which prevents registration of processes of other nodes.
Thanks.
Actually it is well documented, and the expected behaviour as register() is for local process registration.
http://www.erlang.org/doc/man/erlang.html#register-2
Failure: badarg if PidOrPort is not an existing, local process or port, [...]
If you want global registration across your cluster, read http://erlang.org/doc/man/global.html
Note that if you use standard OTP behaviours, (gen_server, etc) most of the time you don't need to use the global module directly.
Crash report (SASL) gives more or less where and why a bug happens.
But is it possible to refine this (the function, the line de code, etc) ?
If you can reproduce the fault, the best way to get more information is to put a dbg trace on sections in question and review that output.
dbg:tracer(),dbg:p(all,c),dbg:tpl(Mod,Func,x).
This usually does the trick for me. Replace Mod and Func with whatever module and function you want to debug.
If you are looking for more detailed post-mortem logging then sasl and the error_logger are your friends. There are of course times when SASL does not give you enough info, if this happens a lot in your system you probably should either learn to understand the SASL output better or write your own log handler. It is quite easy to plug-in your own error handler into SASL and output things as you want.
You will however never get line number as that information is destroyed at compilation time and there is no way for the VM to know which line crashed. It does however know which function and possibly with which arguments, given this it is usually possible to find out where things went wrong. Unless you write very long functions, which IMO is bad code smell and a sign that you should refactor your code to smaller functions.
In general, no. The erlang .beam files does not contain the line numbers from the original code, so it is hard to know at what line the problem occurred. I do have a number of macros I use in my project, included as "log.hrl":
-define(INFO(T), error_logger:info_report(T)).
-define(WARN(T), error_logger:warning_report(
[process_info(self(), current_function), {line, ?LINE} | T])).
-define(ERR(T), error_logger:error_report(
[process_info(self(), current_function), {line, ?LINE} | T])).
-define(DEBUG(Format, Args), io:format("D(~p:~p:~p) : "++Format++"~n",
[self(),?MODULE,?LINE]++Args)).
-define(DEBUGP(Args), io:format("D(~p:~p:~p) : ~p~n",
[self(),?MODULE,?LINE, Args])).
and this does give you some log lines in the program to hunt for. For debugging I often also use the redbug tool from the eper suite:
https://github.com/massemanet/eper
It allows you to trace in realtime whenever a call happens:
Eshell V5.8.3 (abort with ^G)
1> redbug:start("erlang:now() -> stack;return", [{time, 60*1000}]).
ok
2> erlang:now().
{1297,183814,756227}
17:50:14 <{erlang,apply,2}> {erlang,now,[]}
shell:eval_loop/3
shell:eval_exprs/7
shell:exprs/7
17:50:14 <{erlang,apply,2}> {erlang,now,0} -> {1297,183814,756227}
3>
I hope this helps.
I am trying to make Erlang's Inets mode_esi work and run some function. So, far, I did not succeed. Can someone post a minimal example of how to run Inets so that a url like http:localhost:8099/esi/my_mod:foo will invoke the method my_mod:foo/3?
Addition: I have started inets with these commands:
inets:start(),
inets:start(httpd, [{port, 8099}, {server_name, "localhost"}, {document_root, "."},
{server_root, "."}, {erl_script_alias, {"/esi", [my_esi, io]}}]).
The module is:
-module(my_esi).
-export([foo/3]).
foo(Sid, Env, In) -> mod_esi:deliver(Sid, ["bla"]).
But browsing to http://localhost:8099/esi/my_esi:foo result in an error message.
To clarify what has already been said, I'll give a working example (from the ground up). This is to help those who came here from google, mostly because it's how I found it ;)
First, create the module:
# filename: my_esi.erl
-module(my_esi).
-export([foo/3,bar/3]).
foo(Sid, Env, In) -> mod_esi:deliver(Sid, ["foo"]).
bar(Sid, Env, In) -> mod_esi:deliver(Sid, ["bar"]).
Save it, then compile it:
erlc my_esi.erl
You'll now have my_esi.beam
Then run the shell from bash
erl
Within the shell type the following:
inets:start().
{Httpd_State,Httpd_Pid} = inets:start(httpd, [{port, 8099}, {server_name, "localhost"}, {document_root, "."}, {modules,[mod_esi]},{server_root, "."}, {erl_script_alias, {"/esi", [my_esi, io]}}]).
The important part here is:
{modules,[mod_esi]}
If you need other modules, load them by appending them to the list.
To clarify how/why:
I will first admit that it does seems a bit strange at first, and that the documentation was less helpful than I had hoped. However, I realised that:
modules() -> [atom()]
becomes:
{modules, [mod_access, mod_esi, ..., etc.]}
Hope it helps someone :)
I've solved it myself. For some reason, beyond my understanding, the exact same code worked when I invoked Inets with a configuration file (a modified version of inets/examples/server_root/conf/8080.conf). I suppose that the example file includes a more complete list of properties that Inets required than what I listed in inets:start(httpd, [...]). If anyone encounters Inets problem in the future, my advice is to start with the example configuration.
Ok, here goes:
set {erl_script_alias, {"/esi", [my_mod]}} for the inets web server, so the module is accepted.
Write my_mod. Something like:
-module(my_mod).
-export([foo/3]).
foo(SessID, _Env, _Input) ->
mod_esi:deliver(SessID, ["Data ", <<"as">>, " an iolist"]).
Make sure mod_esi is part of inets section called module: {modules, [.., mod_esi, ..}}
This step is very important: Breathe 3 times, recite the holy words "I pray to thee, inets, that you will work this time". Cross your fingers.
Drink a cup of coffee. Tea will not do. It has to be coffee.
Enjoy your web server.