Debugging Pliant programs
Understanding errors report
Here is a sample error report content:
Most error messages are the argument provided to 'error' instruction (see 'Errors handling' paragraph bellow).
Now, if you use Pliant (under Linux) intensively, you will soon discover the two following messages:
means the process accessed an memory address that maps no memory.
The Pliant process received a SIGTERM signal. It means that another Linux process killed the Pliant one.
Processor stack content
error_notify_fatal (ErrorID Str) +14
In this first sample, the exact position in the code is not known because 'error_notify_fatal' is part of the Pliant bootstrap code written in C. What we have between braces is the type of the arguments of the function, so that we can decide which one it was when several functions share the same identifier. Then the +14 at the end of the line is the offset in bytes in the processor native binary code between the beginning and the current execution point in the function, so it's not very helpful.
On the other hand, if the function has been defined in Pliant, the report will look like:
ui_service /pliant/graphic/ui/server/main.pli (internals) 69 5
At the beginning of the line, there is the name of the function, then come the position of the code executing in the function when the error occurred. Position is provided as the module name, followed by line and column number.
Raising an error
Raising an error is the the easiest part:
error "There is a bug here"
Alternatively, and error ID can also be provided:
error error_id_unexpected "There is a bug here"
The error ID is intended to ease errors filtering. Basic error ids are defined in /pliant/language/debug/error1.pli
error error_id_unexpected null "There is a fatal bug here" (null map List)
This is the rarely used most complete version that also enables to provide a list of action records.
error_fatal error_id_unexpected null "There is a fatal bug here" (null map List)
Raises a fatal error that cannot be catched by 'safe' instruction bellow.
Catching an error
Catching the error is performed using 'safe' control (this is try/catch in C++):
and a more complete sample:
constant my_error_id error_allocate_id
'success' and 'failure' blocs are optional.
Testing pending error
Now, the important thing to notice about Pliant errors handling is that when an error is raised by 'error' instruction, the control is not automatically and immediately transfered to the 'failure' bloc.
So, in a function, if you want to escape the function when there is a pending error, you need to include a bloc like this:
This is not very compact, so '?' has been introduced to make it shorter:
some_function_that_could_raise_an_error some_parameter ?
And it is still equivalent to the following:
some_function_that_could_raise_an_error some_parameter ? return
Basically, when '?' has no right part, it's meaning is return if there is a pending error.
The reason for '?' with code on the right is to enable something like:
var Sem s
Please notice that the priority between '?' and ';' has been changed in release 106, so the example will work only with release 106 and above.
'iserror' is a boolean specifying if there is a pending error. 'current_error_id' is the ID associated with the pending error and 'current_error_message' is the associated message.
'shy' is defining a bloc that will automatically be escaped as soon as an error is raised. As a result:
is the same as:
Please notice that Pliant current implementation for 'iserror' and '?' is slow. 'shy' is even worse.
Debugging a Pliant application
When your application is going to production, if you create a file:/log/ directory, all crashes will be logged to file:/log/pliant.log, at least on a Fullpliant system.