Erlang rr() returns missing_chunk - erlang

Newbie question on erlang using by wings 3d shell (windows 7 pro, wings 3d 1.4.1). When I write command to read records definitons:
rr(wings).
I always get an error:
{error,beam_lib,
{missing_chunk,'d:/temp/erlang/lib/wings/ebin/wings.beam',"Abst"}}
What I am doing wrong?

rr/1 "reads record definitions from a module's BEAM file. If there are no record definitions in the BEAM file, the source file is located and read instead."
My guess is that the abstract form hasn't been included in the .BEAM file and that in your installation the source files are not available.
UPDATE: Digging into the shell:read_file_records/2 function, I've found the following:
read_file_records(File, Opts) ->
case filename:extension(File) of
".beam" ->
case beam_lib:chunks(File, [abstract_code,"CInf"]) of
{ok,{_Mod,[{abstract_code,{Version,Forms}},{"CInf",CB}]}} ->
case record_attrs(Forms) of
[] when Version =:= raw_abstract_v1 ->
[];
[] ->
%% If the version is raw_X, then this test
%% is unnecessary.
try_source(File, CB);
Records ->
Records
end;
{ok,{_Mod,[{abstract_code,no_abstract_code},{"CInf",CB}]}} ->
try_source(File, CB);
Error ->
%% Could be that the "Abst" chunk is missing (pre R6).
Error
end;
_ ->
parse_file(File, Opts)
end.
It looks like, if the "Abst" chunk is missing, it doesn't even try to read the source code. What does beam_lib:chunks(File, [abstract_code,"CInf"]) return for you? Which Erlang version are you running?

I am using:
Erlang R14B01 (erts-5.8.2) [rq:1] [async-threads:0]
Eshell V5.8.2 (abort with ^G)
Calling this works fine:
rr("d:/temp/erlang/src/wings.hrl").
Calling:
beam_lib:chunks("wings", [abstract_code,"CInf"]).
returns:
{error,beam_lib,{file_error,"wings.beam",enoent}}

rr/1 requires the actual file name or the relative PATH to the file name. Like this:
rr("wings.hrl").
OR
rr("./apps/MYAPP-1.0/include/my_include_file.hrl").
OR
rr("./src/wings.erl").
In other words, pass it the actual relative PATH from your pwd() to the file which contains the definitions.

Related

yaws appmods Accept-Language A record is not correct

I work with yaws from a docker container for years, basically taken from https://github.com/segeda/docker-yaws/blob/master/Dockerfile:
FROM erlang:20-alpine
...
&& git clone https://github.com/klacke/yaws.git /yaws-src \
...
Things just used to run fine, but all of a sudden my code fails, and I cannot find the error(s). I could not even find a git version which worked when it had before, so I suspect it might not be a code fault, but then -- what could it be?
It cannot be my code, can it? Because I boiled it down to the example given in http://yaws.hyber.org/appmods.yaws and produced the same error:
%% this is my appmod called from yaws
-module(myurl).
-author('kklepper').
-include("../../include/yaws_api.hrl").
%-include("/usr/local/lib/yaws/include/yaws_api.hrl").
% relative or absolute -- either way same result
-export([out/1]).
-define(debug, true).
-ifdef(debug).
-define(trace(Str, X), io:format("Mod:~w line:~w ~p ~p~n",
[?MODULE,?LINE, Str, X])).
-else.
-define(trace(X, Y), true).
-endif.
box(Str) ->
{'div',[{class,"box"}],
{pre,[],Str}}.
out(A) ->
?trace('A', A),
{ehtml,
[{p,[],
box(io_lib:format("A#arg.appmoddata = ~p~n"
"A#arg.appmod_prepath = ~p~n"
"A#arg.querydata = ~p~n",
[A#arg.appmoddata,
A#arg.appmod_prepath,
A#arg.querydata]))}]}.
The file yaws_api.hrl was and still is present:
/yaws # ls -la /usr/local/lib/yaws/include/yaws_api.hrl
-rw-r--r-- 1 1000 50 5563 May 13 2018 /usr/local/lib/yaws/include/yaws_api.hrl
With trace you can see that the A record is not correct -- no A#arg.querydata etc. -- hence the error. Why?
Obviously, querydata, for example, as such is given: lg=en.
Mod:myurl line:22 'A' {arg,#Port<0.2934>,
{{10,255,0,2},52801},
{headers,"keep-alive",
"text/html, application/xhtml+xml, application/xml;q=0.9, image/webp, image/apng, */*;q=0.8, application/signed-exchange;v=b3",
"voxx.b2d",undefined,undefined,undefined,
undefined,undefined,undefined,undefined,
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36",
undefined,[],undefined,undefined,undefined,
undefined,undefined,undefined,undefined,
undefined,
[{http_header,11,'Accept-Language',undefined,
"de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7"},
{http_header,10,'Accept-Encoding',undefined,
"gzip, deflate"},
{http_header,0,"Upgrade-Insecure-Requests",
undefined,"1"}]},
{http_request,'GET',
{abs_path,"/industries?lg=en"},
{1,1}},
{http_request,'GET',
{abs_path,"/industries?lg=en"},
{1,1}},
undefined,"/industries","lg=en","industries","/ci",
"/","/ci/industries",undefined,undefined,<0.163.0>,
[],[],[],"/industries",myurl}
=ERROR REPORT==== 4-Oct-2019::00:46:06 ===
ERROR erlang code threw an uncaught exception:
File: appmod:0
Class: error
Exception: {badrecord,arg}
Req: {http_request,'GET',{abs_path,"/industries?lg=en"},{1,1}}
Stack: [{myurl,out,1,
[{file,"/usr/local/lib/yaws/voxx/ebin/myurl.erl"},{line,29}]},
{yaws_server,deliver_dyn_part,8,
[{file,"yaws_server.erl"},{line,2921}]},
{yaws_server,aloop,4,[{file,"yaws_server.erl"},{line,1274}]},
{yaws_server,acceptor0,2,[{file,"yaws_server.erl"},{line,1073}]},
{proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,247}]}]
By now I ran out of ideas. Any hint?
The data in question seems to be there. I am interested among others in language data and used to get the accepted language from A like so:
get_lang(A) ->
find_lang(find_http_header('Accept-Language', (A#arg.headers)#headers.other)).
find_http_header(Key,Headers) when is_list(Headers) ->
case lists:keysearch(Key,3,Headers) of
{value,{_,_,_,_,Value}} -> Value;
false -> undefined
end.
find_lang(AcceptLanguage) ->
case AcceptLanguage of
undefined ->
"en";
_ ->
L = lists:nth(1,string:tokens(
lists:nth(1,string:tokens(
lists:nth(1,string:tokens(AcceptLanguage, ";"))
,","))
,"-")),
L
end.
Without the correct data structure, this cannot work.
A detail you included in your question shows that your appmod is getting a badrecord exception when trying to access the #arg record that Yaws passes to it. There are a couple ways to get such an exception:
Pass an instance of a data type other than the expected record type to the function. This isn't happening in this case, since Yaws is calling the function and is correctly passing an #arg record instance.
Compile the caller and the called function with two different definitions of the same record. We can simulate this problem in an Erlang shell as follows:
First, define a record #arg containing two fields
Define a function that takes an instance of that record as an argument and returns the value of one of the fields
Redefine the record in the shell to have just one field
Pass an instance of the redefined record to the function, which will cause a badrecord exception
1> rd(arg, {f,g}).
arg
2> F = fun(A) -> A#arg.f end.
#Fun<erl_eval.7.126501267>
3> rd(arg, {f}).
arg
4> F(#arg{f=1}).
** exception error: {badrecord,arg}
Since you're using Yaws 2.0.7 and you're also cloning Yaws from github, it's likely you're compiling some part of your code, probably your appmod, against the Yaws master branch and then running it against 2.0.7. Sometime after I tagged Yaws 2.0.7 on github, I accepted a change that added a new field to the #arg record definition. What this means is that any #arg record Yaws 2.0.7 creates and passes to your appmod will result in a badrecord exception since the appmod expects a record containing the additional field.
I can think of a few ways to avoid this problem:
Get rid of your Yaws github clone and build everything against your installation of Yaws 2.0.7.
In your Yaws clone, git checkout yaws-2.0.7 so that anything you access or use from the clone is the same as what's in your Yaws 2.0.7 installation.
Uninstall Yaws 2.0.7, then compile and install from your Yaws clone. Perhaps apply a local tag first, then build and install from that, so that your deployments can be more easily reproduced, and so that you can grab Yaws updates from github without breaking anything locally.

Erlang exited with reason - undef (with string:find/2 func)

trying to use function string:find/2but every time getting the error
CRASH REPORT Process <0.779.0> with 0 neighbours exited with reason: {{undef,[{string,find,[[<<208,162,51,32,208,190,208,177,209,137,46,44,32,84,51,32,116,111,116,97,108,44>>],[<<208,186,209,128,208,190,208,178>>]],[]},{proxy_layer_cli_handle_req,do_execute_keysearch,4,[{file,\"/opt/proxy_layer/_build/test/lib/proxy_layer/src/proxy_layer_cli_handle_req.erl\"},{line,222}]},{proxy_layer_cli_handle_req,keysearch,3,[{file,\"/opt/proxy_layer/_build/test/lib/proxy_layer/src/proxy_layer_cli_handle_req.erl\"},{line,...}]},...]},...}
when i use it in terminal - everything is okay
1> string:find(<<208,162,51,32,208,190,208,177,209,137,46,44,32,84,51,32,116,111,116,97,108,44>>,<<208,186,209,128,208,190,208,178>>).
1> nomatch
I'm using Erlang 20.1
here is the code which I use:
do_execute_keysearch([First|Rest], PriceList, Keyword, Acc) ->
Id = utils:get_value(<<"Id">>, First),
case utils:get_value(<<"Keywords">>, First) of
<<>> -> do_execute_keysearch(Rest, PriceList, Keyword, Acc);
undefined -> do_execute_keysearch(Rest, PriceList, Keyword, Acc);
Keys ->
case string:find(Keys, Keyword) of
nomatch ->
do_execute_keysearch(Rest, PriceList, Keyword, Acc);
_ ->
Price = find_price_by_service_id(PriceList, Id),
NewAcc = [lists:append(Price, First) | Acc],
do_execute_keysearch(Rest, PriceList, Keyword, NewAcc)
end
end;
UPDATE:
Issue fixed after changing Erlang version in docker container. (Changed to Erlang 20.1)
Don’t know why there are some modules undefined in Erlang 19
So the problem solved now
string:find/2 was added to Erlang in version 20 which is why you were getting an undef error in Erlang 19. The solution is to upgrade to Erlang 20 (which you've already done).
Look at the error more carefully. Or rather, try to reproduce it. Which of these looks more like your error?
1> catch lists:nonexist(<<1>>, <<2>>).
{'EXIT',{undef,[{lists,nonexist,[<<1>>,<<2>>],[]},
{erl_eval,do_apply,6,[{file,"erl_eval.erl"},{line,674}]},
{erl_eval,expr,5,[{file,"erl_eval.erl"},{line,431}]},
{shell,exprs,7,[{file,"shell.erl"},{line,687}]},
{shell,eval_exprs,7,[{file,"shell.erl"},{line,642}]},
{shell,eval_loop,3,[{file,"shell.erl"},{line,627}]}]}}
2> catch lists:nonexist([<<1>>], [<<2>>]).
{'EXIT',{undef,[{lists,nonexist,[[<<1>>],[<<2>>]],[]},
{erl_eval,do_apply,6,[{file,"erl_eval.erl"},{line,674}]},
{erl_eval,expr,5,[{file,"erl_eval.erl"},{line,431}]},
{shell,exprs,7,[{file,"shell.erl"},{line,687}]},
{shell,eval_exprs,7,[{file,"shell.erl"},{line,642}]},
{shell,eval_loop,3,[{file,"shell.erl"},{line,627}]}]}}

Erlang binary: Will this result in a copy?

After reading this document, I'm not sure whether or not the following code will make the run-time copy binaries of A internally.
f(<<>>, A) ->
A;
f(<<X:2/binary, R/binary>>, A) ->
I = binary_to_integer(X, 16),
f(R, <<A/binary, I>>).
My guess is "no", because A isn't sent nor is it deconstructed. Am I right, or did I miss something?
Your code will not result in run-time copying of the A binaries since no sharing of sub-binaries is done. If we manually unroll the sequence of append operations it looks something like
A0 = <<A/binary, SomeByte>>,
A1 = <<A0/binary, SomeByte1>>,
A2 = <<A1/binary, SomeByte2>>,
.....
An = <<An-1, SomeByteN>>.
So we are only appending to the binary resulting from the latest append operation, i.e. there is a single reference to the ProcBin that was created for A0(as described in the efficiency documentation).
Why not use bin_opt_info option ?
For your code :
[root#nimbus bin_test]# erlc +bin_opt_info a.erl
a.erl:8: Warning: OPTIMIZED: creation of sub binary delayed
For the code in https://gist.github.com/wardbekker/5673200
The output is :
[root#nimbus bin_test]# erlc +bin_opt_info test.erl
test.erl:14: Warning: OPTIMIZED: creation of sub binary delayed
[root#nimbus bin_test]# erlc +bin_opt_info test2.erl
test2.erl:8: Warning: variable 'A' is unused
test2.erl:13: Warning: OPTIMIZED: creation of sub binary delayed

Meck behaving strangely for multiple mocked modules

I have following module
-module(bhavcopy_downloader).
-export([download/2]).
download(From, SaveTo) ->
{ok, {{Status, _}, _, Body}} = lhttpc:request(From, "GET", [], infinity),
case Status of
200 -> file:write(SaveTo, Body),
true;
_ -> false
end.
And following tests for the above code
file_download_test_() ->
{foreach,
fun() ->
meck:new(lhttpc)
meck:new(file, [unstick])
end,
fun(_) ->
meck:unload(file),
meck:unload(lhttpc)
end,
{"saves the file at specified location",
fun() ->
meck:expect(lhttpc, request, 4, {ok, {{200, "OK"}, [], <<"response">>}}),
meck:expect(file, write_file, fun(Path, Data) ->
?assertEqual(Path, "~/Downloads/data-downloader/test.html"),
?assertEqual(Data, <<"response">>)
end),
?assertEqual(true, bhavcopy_downloader:download("http://google.com", "~/Downloads/data-downloader/test.html")),
?assert(meck:validate(file))
end}]
}.
When I run the tests I get following error (only part of the error pasted below for brevity). Looking at the error below, I am kind of feeling that file module is not being mocked (or the mock of file module being overridden when I set the other mock using meck:new(lhttpc). What could be going wrong here?
=ERROR REPORT==== 16-Feb-2013::20:17:24 ===
** Generic server file_meck terminating
** Last message in was {'EXIT',<0.110.0>,
{compile_forms,
{error,
[{[],
[{none,compile,
{crash,beam_asm,
{undef,
[{file,get_cwd,[],[]},
{filename,absname,1,
[{file,"filename.erl"},{line,67}]},
{compile,beam_asm,1,
[{file,"compile.erl"},{line,1245}]},
{compile,'-internal_comp/4-anonymous-1-',2,
[{file,"compile.erl"},{line,273}]},
{compile,fold_comp,3,
[{file,"compile.erl"},{line,291}]},
{compile,internal_comp,4,
[{file,"compile.erl"},{line,275}]},
{compile,'-do_compile/2-anonymous-0-',2,
[{file,"compile.erl"},{line,152}]}]}}}]}],
[{"src/lhttpc_types.hrl",
[{31,erl_lint,{new_builtin_type,{boolean,0}}},
{31,erl_lint,{renamed_type,bool,boolean}}]}]}}}
This is a catch 22 in Meck, caused by the fact that Meck uses the Erlang compiler, which in turns uses the file module. When Meck tries recompile the file module it needs the file module (through the compiler) and thus crashes.
As of this moment, Meck doesn't handle mocking the file module. Your best alternative is to wrap the file module calls in another module and mock this module instead.
(It is theoretically possible to fix this in Meck by using the internals of the compiler and the code server instead, for example erlang:load_module/2, however this is quite tricky and needs to be designed and tested well)

Avoid NZEC error in Erlang in SPOJ

I've written code in Erlang, and I get the correct answer on my machine. But when I submit it on SPOJ it gives an NZEC (non zero exit code) error. I have used built-in functions like halt() and init:stop(), and their specification clearly says that they are used to avoid non-zero exit code error. But still I get the same error. How can I solve this problem?
EDIT The code as required by a comment:
-module(factorial).
-export([main/0]).
main() ->
{ok, [No_of_cases]} = io:fread("", "~d"),
loop(No_of_cases).
loop(0) ->
%init:stop();
halt(1);
loop(No_of_cases) ->
{ok, [Number]} = io:fread("", "~d"),
ResultFactorial = find_factorial(Number,1),
io:format("~p~n",[ResultFactorial]),
loop(No_of_cases-1).
find_factorial(0,Product) ->
Product;
find_factorial(Number,Product) ->
find_factorial(Number-1,Product*Number).
I got the answer. The trick is that your module name always has to be tested and the entry point should be function main . For example, after compilation it should be run as tested:main().

Resources