I've guessed a couple of the erlang:system_info/1 variants such as:
10> erlang:system_info(schedulers).
4
11> erlang:system_info(cpu).
** exception error: bad argument
in function erlang:system_info/1
called as erlang:system_info(cpu)
12> erlang:system_info(cpu_arch).
** exception error: bad argument
in function erlang:system_info/1
called as erlang:system_info(cpu_arch)
13> erlang:system_info(memory).
** exception error: bad argument
in function erlang:system_info/1
called as erlang:system_info(memory)
14> erlang:system_info(version).
"5.10.4"
But is there a way, either via introspection, or a global database of some sort, to list all the available system_info arguments ?
Refer to the documentation for erlang:system_info/1. It's listed over several sections with descriptions for what each atom represents. This is the most comprehensive list of supported atoms outside of the Erlang/OTP source itself (and there are a few undocumented parameters).
There is no language feature which would allow you to list all of the possible atoms.
Related
I want to run a (python3) process from my (yap) prolog script and read its output formatted as a list of integers, e.g. [1,2,3,4,5,6].
This is what I do:
process_create(path(python3),
['my_script.py', MyParam],
[stdout(pipe(Out))]),
read(Out, OutputList),
close(Out).
However, it fails at read/2 predicate with the error:
PL_unify_term: PL_int64 not supported
Exception ignored in: <_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'>
BrokenPipeError: [Errno 32] Broken pipe
I am sure that I can run the process correctly because with [stdout(std)] parameter given to process_create the program outputs [1,2,3,4,5,6] as expected.
Weird thing is that when I change the process to output some constant term (as constant_term) it still gives the same PL_int64 error. Appending a dot to the process' output ([1,2,3,4,5,6].) doesn't solve the error. Using read_term/3 gives the same error. read_string/3 is undefined in YAP-Prolog.
How can I solve this problem?
After asking at the yap-users mailing list I got the solution.
Re-compiled YAP Prolog 6.2.2 with libGMP option and now it works. It may also occur in 32-bit YAP.
I was just playing with records, and am stuck trying to write a function that works with records. I think the problem is how to read the record definition into my module file.
The reocords.hrl file:
% Modeling a todo list
-record(todo, {status=reminder, who=joe, text}).
And then the use_records.erl file:
%% Use the records defined in "records.hrl"
-module(use_records).
-export([todo_to_tuple/1]).
rr("records.hrl").
todo_to_tuple(#todo{who=W, text=T} = R) -> {W, T}.
When I try to compile it, I get:
24> c(use_records).
use_records.erl:5: variable 'T' is unbound
use_records.erl:5: variable 'W' is unbound
use_records.erl:5: record todo undefined
use_records.erl:5: Warning: variable 'R' is unused
error
The error is the same if I remove the rr("records.hrl") line. So I suppose the real issue is being able to read the record definition (or not?). Please help!
rr/1 is used include record definition only in the shell.
In order to include record definition in your code use:
-include("records.hrl")
I have a C++ CORBA server which implements an interface throwing a user defined exception.
I am easily able to catch the specific exception when client and server are both implemented in C++ (tested using both TAO orb and omniORB).
But when I invoke the same method from Erlang (using orber), the exception appears as generic exception and not as specific user defined exception.
To test this I just used a simple IDL -
interface Messenger {
exception cirrus_error{
short error_code;
string error_desc;
};
boolean send_message(in string user_name,
in string subject,
inout string message) raises (cirrus_error);
};
If both server and client are in C++ - the exception I get is (for testing I coded it to always throw the user exception)
CORBA exception: cirrus_error (IDL:Messenger/cirrus_error:1.0)
But when invoked via Erlang - I get -
** exception throw: {'EXCEPTION',{'UNKNOWN',[],1330446337,'COMPLETED_MAYBE'}}
in function corba:raise/1
Do I need to do something special while stating Orber application to enable the correct behaviour?
Edit - This is how I call server from erlang -
On Erlang prompt, this is what I do -
1> orber:jump_start().
2> O = corba:string_to_object(IORStr).
3> 'Messenger':send_message(O, "s", "t", "f").
** exception throw: {'EXCEPTION',{'UNKNOWN',[],1330446337,'COMPLETED_MAYBE'}}
in function corba:raise/1
You need to register your IDL definitions into the orber interface repository (IFR) before invoking the method. If your IDL file is named messenger.idl, for example, compiling it creates oe_messenger.erl, which provides the oe_register/0 function. Calling it registers information about your user-defined exception into the IFR, which orber's CDR decoding uses to be able to properly decode any responses containing that exception:
1> orber:jump_start().
...
2> ic:gen(messenger).
Erlang IDL compiler version 4.4
ok
3> make:all().
Recompile: Messenger
Recompile: Messenger_cirrus_error
Recompile: oe_messenger
oe_messenger.erl:65: Warning: function oe_get_top_module/4 is unused
oe_messenger.erl:91: Warning: function oe_destroy_if_empty/2 is unused
up_to_date
4> oe_messenger:oe_register().
ok
5> M = corba:string_to_object(IORStr).
...
6> 'Messenger':send_message(M, "a", "b", "c").
** exception throw: {'EXCEPTION',{'Messenger_cirrus_error',"IDL:Messenger/cirrus_error:1.0",
1234,"yep, an error"}}
in function corba:raise/1 (corba.erl, line 646)
Update: The reason this extra IFR registration step is needed in orber, while rarely if ever being necessary in C++ ORBs, is due to some flexibility in the CORBA specification and also to C++ ORB development traditions. The original CORBA specification was in part a compromise between static and dynamic language camps. The dynamic camp insisted on the IFR being in the spec as they needed it for retrieving type information at runtime (and clearly they got their wish, since it's always been a part of CORBA), but the static camp assumed the IFR was unnecessary since all necessary type information could be encoded in C/C++ code generated from IDL definitions. The C++ ORB development community has traditionally followed the code generation approach and treated the IFR as an optional runtime component, and the C++ ORBs used in this question retrieve information about the user-defined cirrus_error exception from generated stubs and skeletons. But ORBs written in other languages, such as Smalltalk and Erlang, have chosen to use the IFR as a normal component of the ORB runtime, and so they require registration of type information into the IFR in order for it to be available to the ORB runtime. It would definitely be possible in Erlang, though, to generate information about user-defined exceptions into stubs/skeletons and have the runtime retrieve it from there.
What does "The run procedure option is not allowed with member type RPGLE" mean?
what does "The run procedure option is not allowed with member type RPGLE" mean?
Apparently that is the error message identifier PDM0365 with first-level text "The Run Procedure option is not allowed with member type &1." from the Message File (MSGF) QUOMSGF in library QPDA. In the second level text [visible after F1=Help is pressed with the cursor positioned on that message id, or in Display Message Description (DSPMSGD) for that message Id and message file] what is the cause and the recovery for the error condition is further explained; i.e. the assistance requested on this site, probably could have been resolved by asking that the system should provide the Help:
Cause . . . . . : You cannot run a procedure with this type.
Recovery . . . : The following member types can be run as procedures: REXX,
OCL36, BASP, BASP38.
With the replacement text for the replacement-variable &1 being RPGLE, the indication is that the option-16="Run Procedure" was issued against a member listed in the Work With Members Using PDM (WRKMBRPDM) feature, and the TYPE for the member was RPGLE instead of one of the listed as supported member types noted in the Recovery text.
Additionally, if under the heading Opt [the USEnglish abbreviation for Option] the F1=Help were pressed [instead of] where the option 16 was typed, the following Help Text would be presented that explains what are the options that can be specified and what each of the system-supplied numeric options will effect:
Help Options - Help
16=Run procedure
Type 16 to run a source member with a member type of REXX,
OCL36, BASP, or BASP38. If you try to run a member with a type
that cannot be run, you receive an error message. To run an
OCL36 procedure, the file name must be QS36PRC. You can have
the member run in batch mode or interactively depending on what
you specified in the Run in batch prompt on the Change Defaults
display.
Therefore if a Run option is not an eligible task to perform against the member of type=RPGLE, perhaps review the other options for what they might provide. Here are two, one conspicuous by specific mention of support for the type-RPGLE in the Option help-text and another much more subtle by only an allusion to types that reflect an ILE source type [with [...] denoting snipped content from that help]:
[...]
14=Compile
Type 14 to compile one or more members. The system creates an
object based on the member being compiled. The member is
compiled interactively or in batch mode, depending on what you
have specified on the Change Defaults display.
The following member types can be compiled: [...]
PLI38, PNLGRP, PRTF, PRTF38, QRY38, RMC, RPG, RPGLE, RPG36,
RPG38, RPT, RPT36, RPT38, SPADCT, SQLC, SQLCPP, SQLCBL,
[...]
When the programming development manager compiles a program
[...]
15=Create module
Type 15 to create a module object for an ILE source type.
[...]
For the latter, to create a Module (*MOD) object versus to create a Bound Program (*PGM) from the RPGLE type which is a contraction of RPG and ILE, denoting that type as an ILE source type.
So instead of using Option-16, use either of Option-14 or Option-15 to compile the ILE RPG source into an executable [*PGM] or a linkable [*MOD] object.
Option 16 (Run procedure) only applies to REXX procedures (and maybe some others). You can't use it to run an RPG/COBOL/C program. It MIGHT work to run a CL program, but I don't think so.
To run a program, either CALL it from the command line or create your own PDM option.
The SEU error may or may not be an error - SEU hasn't been kept up-to-date with all the new features of the RPGLE language. Remember that SEU is simply a source editor/validator.
If you were able to compile the RPG program (using PDM option 14 for CRTBNDRPG or option 15 for CRTRPGMOD followed by running the CRTPGM command) then the SEU 'problem' isn't a problem at all.
consider the code below:
-module(except).
-compile(export_all).
divone(X)-> erlang:error({badnews,erlang:get_stacktrace()}),1/X-1.
tryreturn(X)->
try divone(X) of
Val->{result,2/Val}
catch
exit:Reason->{exit,Reason};
throw:Throw->{throw,Throw};
error:Error->{error,Error}
end.
test the code in shell:
Eshell V5.9.1 (abort with ^G)
1> c(except).
{ok,except}
2> except:tryreturn(10). **%why cant't get stack trace info here?**
{error,{badnews,[]}}
3> except:tryreturn(10). **%why can get here?**
{error,{badnews,[{except,divone,1,
[{file,"except.erl"},{line,4}]},
{except,tryreturn,1,[{file,"except.erl"},{line,7}]},
{erl_eval,do_apply,6,[{file,"erl_eval.erl"},{line,576}]},
{shell,exprs,7,[{file,"shell.erl"},{line,668}]},
{shell,eval_exprs,7,[{file,"shell.erl"},{line,623}]},
{shell,eval_loop,3,[{file,"shell.erl"},{line,608}]}]}}
If there hasn't been any exceptions, the stacktrace returned by erlang:backtrace() is empty.
Something more helpful than erlang:backtrace() for you would be something that includes the instruction pointer and the process's callstack, irrespective of if you've caught an exception.
This should be the ticket:
io:format("~s~n", [element(2, process_info(self(), backtrace))]).
(Naturally, self can be freely exchanged with another Pid)
According to documentation:
Gets the call stack back-trace (stacktrace) of the last exception in the calling process as a list of {Module,Function,Arity,Location} tuples. Field Arity in the first tuple can be the argument list of that function call instead of an arity integer, depending on the exception.
Note the last exception in above text. During your first call, there was not any exception yet, so there is not any stacktrace to return. Then you make error class[1] exception using erlang:error/1 so next call returns stacktrace of the previous call!
There is idiom how to get stacktrace of the current code:
try throw(foo) catch foo -> erlang:get_stacktrace() end.
or using older (obsolete) way:
catch throw(foo), erlang:get_stacktrace().
[1]: There are three classes of exception: throw, error, exit.