"init terminating in do_boot" is thrown when executing Erlang script - erlang

Here's my code in 'factorial.erl':
-module(factorial).
-author("jasonzhu").
%% API
-export([fac/1]).
fac(0) -> 1;
fac(N) -> N * fac(N-1).
When interacting this code in prompt, it works fine:
1> c(factorial).
{ok,factorial}
2> factorial:fac(20).
2432902008176640000
But if I compile and execute it from command line, some errors occurred.
Jasons-MacBook-Pro:src jasonzhu$ erlc factorial.erl
Jasons-MacBook-Pro:src jasonzhu$ erl -noshell -s factorial fac 20 -s init stop
{"init terminating in do_boot",{badarith,[{factorial,fac,1,[{file,"factorial.erl"},{line,8}]},{init,start_it,1,[]},{init,start_em,1,[]}]}}
Crash dump was written to: erl_crash.dump
init terminating in do_boot ()
Could anyone help me out? I'm a newbie on Erlang, many thanks!

-noshell syntax is
erl -noshell -s Module Function Arguments
where Arguments is a list of atoms. So you have to get 'fac' argument from list and convert it to integer.
This
-module(factorial).
-export([fac/1]).
fac([N]) ->
X = fac(list_to_integer(atom_to_list(N))),
io:format("~p~n", [X]);
fac(0) -> 1;
fac(N) -> N * fac(N-1).
works
>>> erl -noshell -s factorial fac 20 -s init stop
2432902008176640000

This option is not specific to the OP's question just may be useful for someone coming from “init terminating in do_boot” search in addition to the official doc How to Interpret the Erlang Crash Dumps
If your code is laying around for some time and you start working with it again, recompilation may make this error gone
Delete _build/ directory
Delete rebar.lock file
Compile /dir_with_rebarconfig$ rebar3 release

Related

Error executing .sh command using Erlang build

I get an error like this when I execute the command. How do I fix this error?
Erlang Version: 22.3
Operating System: Centos OS 7
{"init terminating in do_boot",{{badmatch,{error,{1,erl_parse,["syntax error before: ","','"]}}},[{init,start_it,1,[]},{init,start_em,1,[]},{init,do_boot,3,[]}]}}
init terminating in do_boot ({{badmatch,{error,{1,erl_parse,[_]}}},[{init,start_it,1,[]},{init,start_em,1,[]},{init,do_boot,3,[]}]})
Crash dump is being written to: erl_crash.dump...done
It is syntax error, not difficult to debug.
You should have source code and check the program and write some debug statement if necessary.
Mot likely the $1 and $option are not resolving to correct values...
As I try the following command, trying to simulate what might be executing as part of the shell script, I get the same error as you are...
$ erl -noshell -pa /tools_core/ebin -pa ./ebin -eval "make:all(),gen_data:gen(,)" -s c q
{"init terminating in do_boot",{{badmatch,{error,{1,erl_parse,["syntax error before: ","','"]}}},[{init,start_it,1,[]},{init,start_em,1,[]},{init,do_boot,3,[]}]}}
init terminating in do_boot ({{badmatch,{error,{1,erl_parse,[_]}}},[{init,start_it,1,[]},{init,start_em,1,[]},{init,do_boot,3,[]}]})
Crash dump is being written to: erl_crash.dump...done
So most likely, you should check what values they are resolving to. If they are resolving to an empty value, then erlang parse will fail. Since it says before ,, I suspect it's the resolution of $1 which is not happening properly.
can you echo these values and let us know what are they resolving to??
Most likely, $1 should take the command line argument which gets passed along while invoking this shell script. Since its your environment, can't say much. But please try and share what $1 is resolving to in your case.

Using Elixir module from Erlang fails

I am trying to use in Erlang module a beam-file compiled from Elixir source. It raises error when I run Erlang node but I can use the code directly from Elixir.
Elixir module:
defmodule Recursion do
def print_multiple_times(msg, n) when n <= 1 do
IO.puts msg
end
def print_multiple_times(msg, n) do
IO.puts msg
print_multiple_times(msg, n - 1)
end
end
Erlang module:
-module(use_recur).
-define(elixir__recursion, 'Elixir.Recursion').
-export([hey/0]).
hey() ->
?elixir__recursion:print_multiple_times("Hello!", 3).
Compile both:
$ rm -f *.beam
$ elixirc recursion.ex
$ erlc use_recur.erl
Run Erlang:
$ erl -run use_recur hey -run init stop -noshell {"init terminating in do_boot",{undef,[{'Elixir.IO',puts,["Hello!"],[]},{'Elixir.Recursion',print_multiple_times,2,[{file,"recursion.ex"},{line,7}]},{init,start_em,1,[]},{init,do_boot,3,[]}]}}
init terminating in do_boot ({undef,[{Elixir.IO,puts,Hello!,[]},{Elixir.Recursion,print_multiple_times,2,[{},{}]},{init,start_em,1,[]},{init,do_boot,3,[]}]})
Crash dump is being written to: erl_crash.dump...done
Elixir script:
Recursion.print_multiple_times "Hello!", 3
Runs successfully:
$ elixir elx_recur.exs
Hello!
Hello!
Hello!
Why does it happen? I'd say Erlang's output should be the same.
The error means that Erlang could not find a module named 'Elixir.IO'. This module is part of core Elixir. You'll need to add the ebin folder of your Elixir installation to Erlang's load path using -pa (or other similar flags like -pz) to make Erlang load Elixir's core libraries, as that folder contains the compiled .beam files of Elixir core, including Elixir.IO.beam.
erl -pa /path/to/elixir/ebin ...

How can I pass command-line arguments to a Erlang program?

I'm working on a Erlang. How can I pass command line parameters to it?
Program File-
-module(program).
-export([main/0]).
main() ->
io:fwrite("Hello, world!\n").
Compilation Command:
erlc Program.erl
Execution Command-
erl -noshell -s program main -s init stop
I need to pass arguments through execution command and want to access them inside main written in program's main.
$ cat program.erl
-module(program).
-export([main/1]).
main(Args) ->
io:format("Args: ~p\n", [Args]).
$ erlc program.erl
$ erl -noshell -s program main foo bar -s init stop
Args: [foo,bar]
$ erl -noshell -run program main foo bar -s init stop
Args: ["foo","bar"]
It is documented in erl man page.
I would recommend using escript for this purpose because it has a simpler invocation.
These are not really commandline-parameters, but if you want to use environment-variables, the os-module might help. os:getenv() gives you a list of all environment variables. os:getenv(Var) gives you the value of the variable as a string, or returns false if Var is not an environment-variable.
These env-variables should be set before you start the application.
I always use an idiom like this to start (on a bash-shell):
export PORT=8080 && erl -noshell -s program main
If you want "named" argument, with possible default values, you can use this command line (from a toy appli I made):
erl -pa "./ebin" -s lavie -noshell -detach -width 100 -height 80 -zoom 6
lavie:start does nothing more than starting an erlang application:
-module (lavie).
-export ([start/0]).
start() -> application:start(lavie).
which in turn start the application where I defined default value for parameters, here is the app.src (rebar build):
{application, lavie,
[
{description, "Le jeu de la vie selon Conway"},
{vsn, "1.3.0"},
{registered, [lavie_sup,lavie_wx,lavie_fsm,lavie_server,rule_wx]},
{applications, [
kernel,
stdlib
]},
{mod, { lavie_app, [200,50,2]}}, %% with default parameters
{env, []}
]}.
then, in the application code, you can use init:get_argument/1 to get the value associated to each option if it was defined in the command line.
-module(lavie_app).
-behaviour(application).
%% Application callbacks
-export([start/2, stop/1]).
%% ===================================================================
%% Application callbacks
%% ===================================================================
start(_StartType, [W1,H1,Z1]) ->
W = get(width,W1),
H = get(height,H1),
Z = get(zoom,Z1),
lavie_sup:start_link([W,H,Z]).
stop(_State) ->
% init:stop().
ok.
get(Name,Def) ->
case init:get_argument(Name) of
{ok,[[L]]} -> list_to_integer(L);
_ -> Def
end.
Definitively more complex than #Hynek proposal, but it gives you more flexibility, and I find the command line less opaque.

not output exception stack trace in EUnit

I'm write a test with EUnit, but not anything exception detail output in console.
exp_test() ->
?assertEqual(0, 1/0).
Run this module:exp_test() in the Erlang Shell output following
** exception error: bad argument in an arithmetic expression
in function exp_test:'-exp_test/0-fun-0-'/1 (src/test/eunit/xxx_test.erl, line 8)
But in EUnit output following
> eunit:test(xxx).
> xxx_test: exp_test...*failed*
::badarith
EUnit not output anything exception trace info
Im trying the verbose config in eunit, but no effect.
I want to output some exception detail in eunit test result.
Thanks~
The problem seems to be that the version of eunit shipped with R15 does not understand the new stack trace format in R15. This has been fixed in the development version of eunit: github.com/richcarl/eunit
For example:
Eshell V5.10 (abort with ^G)
1> eunit:test(fun() -> (fun() -> exit(foo), ok end)() end).
erl_eval: expr...*failed*
in function erl_eval:do_apply/6 (erl_eval.erl, line 576)
in call from erl_eval:exprs/5 (erl_eval.erl, line 118)
**exit:foo
I hope this will make it into the next release of OTP R15.
This is a known problem in eunit as released in R15B and R15B01. This has been fixed in release R15B02. If you're stuck with an earlier version, you can download and apply a patch:
A workaround for releases before R15B02
You can fix the problem in your local installation by recompiling the affected module:
Download and unpack the Erlang/OTP sources, if you don't have them already.
wget http://www.erlang.org/download/otp_src_R15B01.tar.gz
tar xzf otp_src_R15B01.tar.gz
cd otp_src_R15B01
Download and apply the patch.
wget -O eunit-stacktrace.patch https://github.com/erlang/otp/commit/73b94a990bb91fd263dace4ccbaef6ff727a9637.patch
patch -p1 < eunit-stacktrace.patch
Recompile eunit_lib.erl.
cd lib/eunit
erlc -o ebin -I include src/eunit_lib.erl
Copy the new eunit_lib.beam over the old one (usually somewhere below /usr/local).
ls /usr/local/lib/erlang/lib/eunit-2.2.2/ebin/
# check that eunit_lib.beam is actually there
sudo cp ebin/eunit_lib.beam /usr/local/lib/erlang/lib/eunit-2.2.2/ebin/
Eunit is quite old and while it is officially maintained by the OTP team at Ericsson, it is usually uncared for. Eunit currently has the bad habit of eating up stack traces, and hasn't been updated for R15's line numbers in exceptions.
I wouldn't argue that "that's how it's supposed to work". No sane test tool should hide exception details and line numbers for you.
A trick I like to use is ?debugVal(catch expr) where expr is either a begin end block
or a call to the failing function. For example, ?debugVal(catch begin 1 = 2 end) will output a stacktrace in your tests.

Erlang VM -s argument misbehaving

When I start up a function within the erl shell, it works fine. When I try to invoke the same function with erl ... -s module function, it fails.
The line of code that eventually fails is:
start(Port) ->
mochiweb_http:start([{port, Port}, {loop, fun dispatch_requests/1}]).
I'm positive that Port is set correctly. My error message is:
=CRASH REPORT==== 17-Jan-2010::00:21:09 ===
crasher:
initial call: mochiweb_socket_server:acceptor_loop/1
pid: <0.65.0>
registered_name: []
exception exit: {error,closed}
in function mochiweb_socket_server:acceptor_loop/1
ancestors: [mochiweb_http,<0.1.0>]
messages: []
links: []
dictionary: []
trap_exit: false
status: running
heap_size: 377
stack_size: 24
reductions: 93
neighbours:
I tried the debugger and it lets me step through right up until the line of code above is given. After I pass that, it gives me this crash report.
Any help is greatly appreciated.
Hm, I think that should work.
Are all modules compiled with the same compiler version? IIRC there might be weird errors on the socket level if not.
BTW, you might call your entry point function start which is the default for -s.
Alternatively you can try the -eval option:
erl -eval 'module:start(9090).'
when using -s, the arguments are collected into a list, so the port would actually be enclosed in a list. you can check both cases (list or int) with a wrapper function (like start([Port])).
When you use -s to run Erlang functions, arguments are put into a list of atoms. When you use -run to run Erlang functions, arguments are put into a list of strings.
If you need an integer value to pass on, you will need to do the proper conversions. If you want to cover all cases, something like this could help:
start([Port]) when is_atom(Port) ->
start([atom_to_list(Port)]);
start([Port]) when is_list(Port) ->
start(list_to_integer(Port));
start(Port) when is_integer(Port) ->
mochiweb_http:start([{port, Port}, {loop, fun dispatch_requests/1}]).
Consult the man page for erl ("erl -man erl") for details.

Resources