[Gambas-user] using try when access devices shadow the errors

Tobias Boege taboege at gmail.com
Wed Aug 1 21:10:00 CEST 2018


On Wed, 01 Aug 2018, PICCORO McKAY Lenz wrote:
> in  other email from tobias, mentioned that Catch may shadowed the errors
> if  i used devices..
> 

That's twisting what I said in many directions. It has nothing to do
with devices.

> '' generic open port procedure
>     Try SComm.Close()
>     SComm = New SerialPort As "SComm"
>     SComm.PortName = puerto
>     SComm.Speed = 9600
>     SComm.Parity = 0
>     SComm.DataBits = 8
>     SComm.StopBits = 1
>     SComm.FlowControl = 2
>     Try SComm.Open()
> Catch
>     Print "error device" & Error.Text
> 
> exactly if "Try" wil ignore errors, so how to property propagate error to
> up class in inherits?
> 
> a good question for good desing, so we cannot always write tode for school!
> 

If you use

  Try SComm.Open()

then any error raised by the Open call is ignored. Normally, an error aborts
the Gambas program, like throwing an exception, but you cancel that when you
use Try. As was mentioned in the other thread, even when you use Try, you
can still find out if an error happened. The interpreter will set the the
keyword Error to True in Boolean context when an error happened:

  Try SComm.Open()
  If Error Then
    ' react to the error here
  Endif

Now this can be a bit confusing because the error keyword in Gambas means
three things, even at the top level:

  * It is the name of a class Error in the gb component, where more
    information about the last error that occured is stored,
  * It is a printing instruction like Print, but instead of standard output,
    it prints to standard error,
  * The last meaning is the one that is relevant to the code above:
    it is True if and only if the last Try statement detected an error.

The first is documented here [1], the latter two here [2].

Now to your question: if you want to propagate an error, simply don't
catch it, neither with Try nor Catch. Gambas will propagate an error
that happens in a function automatically to the calling function, and
if that doesn't handle it, the error is forwarded to the next caller
and so forth. This chain stops once any function handles the error,
either by having the function call that leads to the error prefixed by
Try or by having a Catch block.

On the other hand, if you arrive at the outmost function on the call stack,
and no function bothers handling the error, the interpreter will look for
the Static Public Sub Application_Error [3] in the startup class of your
project. This is a global "catch all" event handler that you can use to
maybe save important work.

If an error propagates to the outmost scope, then the interpreter will
display an error message and abort your program.

Something more advanced: you can catch and rethrow errors in Gambas
using Error.Propagate():

  Dim iTries As Integer = 5

  Do
    Try SComm.Open()
    Dec iTries
  While Error and iTries > 0
  If Error Then Error.Propagate()

This will try to connect five times (without changing any parameter) and
after the fifth failure, it will just take the error produced by the
Open() method and forward it.

This is a bit of a silly example for a serial port, but the idea is that
you can catch an error using Try, then you attempt to recover from the
error in a way that fits your problem, and if that also doesn't succeed,
you propagate the error to your caller.

The Try method is good if you have a chance of recovering from the error
inside the function itself. On the other hand, the Catch block [4] does
not let you resume execution of your function: when an error happens, the
interpreter sends you straight into the Catch block, which is executed
and the "error flag" is cleared. Once you went through the Catch block,
the function returns normally and the error is forgotten, not propagated,
because it is assumed that you used the Catch block to handle it.
The Catch block would be more useful in a function which expects its
callees to fail sometimes and in that case abort the mission altogether,
but without crashing the whole process.

And finally, don't forget the Finally block [5]. It can occur after a Catch
block in every function and the code in there is executed even after the
Catch block in case of error, so immediately before the function returns,
*and* it is also executed when no error happens, immediately before the
function returns. This is a great way to free temporary memory when you
are working with a C library in your function or to otherwise clean up
resources your function uses, like database connections, to avoid memory
leaks, in case one of your callers does handle the error and your program
keeps running.

Notice that all I talked about involved the words "caller", "callee" and
possibly "call stack". Error handling in Gambas (and probably everywhere
else) goes along the dynamic scope. You can catch an error which happens
in a function only if you are that function or if you called it (or called
a function that called it, and so on). What you can *not* do is propagate
an error from one class into another class you inherit from.

So, in the context of that other thread you mentioned, if you have two
classes GenericPrinter and EpsonPrinter and you call

  $hEpson.Write()

then it will dispatch to the specific Write method of the EpsonPrinter object.
If an error happens in there, you can *not* propagate and handle it inside
the GenericPrinter.Write method. If you call

  $hEpson.Open()

(for which EpsonPrinter has no special version, so it dispatches to the
generic Open method of GenericPrinter), and an error occurs there, then
the code in the GenericPrinter will have to handle the error and even though
you have an EpsonPrinter object there, the EpsonPrinter class is not in
charge of handling the error, as you are executing a method defined in
GenericPrinter.

Regards,
Tobi

[1] http://gambaswiki.org/wiki/comp/gb/error
[2] http://gambaswiki.org/wiki/lang/error
[3] http://gambaswiki.org/wiki/comp/gb/application
[4] http://gambaswiki.org/wiki/lang/catch
[5] http://gambaswiki.org/wiki/lang/finally

-- 
"There's an old saying: Don't change anything... ever!" -- Mr. Monk


More information about the User mailing list