3

I'm looking for the equivalent semantics to the popular Try-Finally exception cleanup pattern, e.g. Why use try … finally without a catch clause?

The idea is that you have cleanup steps that need to happen regardless of whether the code succeeds or fails, but the cleanup code shouldn't interfere with reporting and handling the error. Something still went wrong and the exception should still propagate.

I would like to write something like this:

O TempFile:(/NEW:/WRITE:/STREAM)
U TempFile
L +LockName
TRY {
 ...code that uses TempFile and may throw an error
} FINALLY {
 //Be sure to delete file whether we have an error or not
 O TempFile:(/DELETE)
 C TempFile
 //Be sure to release lock
 L -LockName
}
... Rest of code that should only execute if there was no error

But the TRY...CATCH syntax in ObjectScript does not support the FINALLY clause.

In particular, it's important that both of these things normally done by finally blocks hold true:

  • The cleanup code is always run before execution is returned to the caller, both when there was an error and when everything ran normally.
  • If an error occurs, the original error with its code location, context and stack are propogated up the call stack to the original caller. The cleanup code shouldn't interfere with debugging.

I can't simply use a regular TRY...CATCH block because CATCH will eat the exception and stop the correct error context from being passed up the chain. Maybe there is a way to re-throw the original exception without messing up the error context?

Community
  • 1
  • 1
Chris Smith
  • 5,326
  • 29
  • 29
  • Look at this thread on InterSystems Developer Community about try/catch in COS: https://community.intersystems.com/post/try-catch-block-i-usually-use-cos Hope this helps. – Evgeny Shvarov Jun 29 '16 at 23:13

2 Answers2

2

you can throw caught error, and it will be original error, with original place of error and anything else, so Try-Finally may looks like below.

try {
    // some code that could be with errors
} catch ex {
}
// finally

throw:$g(ex) ex
// rest code that can't execute if was error
DAiMor
  • 3,185
  • 16
  • 24
  • That doesn't seem to work. I tried the sample code with a divide by zero error in the TRY block and get a error on the THROW line. – Chris Smith Aug 19 '14 at 21:13
  • It works for me, and I tested on 2014.1 with divide by zero too, and caught error correct. Well, I'll check it later. – DAiMor Aug 20 '14 at 04:16
  • I an not sure how did you get it, but maybe you have to have another try-catch block on top level of stack. "A THROW within a CATCH block passes control up the execution stack to the next error handler. If the exception is a %Exception.SystemException object, the next error handler can be any type (CATCH or traditional); otherwise there must be a CATCH to handle the exception or a error will be thrown." – DAiMor Aug 20 '14 at 06:27
  • The THROW in your sample code is outside the CATCH block, not inside. – Chris Smith Aug 20 '14 at 14:30
  • The whole idea is that I don't want the cleanup code to interfere with error handling. I can't always change the code that calls my code that may raise the error. I need the original error to propagate as if there was nothing in between (after the cleanup code runs); that's the way FINALLY blocks are supposed to work. – Chris Smith Aug 20 '14 at 14:58
  • as I told earlier, my sample works well. I am sure, that THROW can be in any place where you want, not only in try-catch block, but it must be catch in level above. In my example, after catching error you could execute any other code, like close objects, files or anything else, and throw the error if it was for level above. Can you write your full example and zversion ? – DAiMor Aug 20 '14 at 21:41
0

Would not it be an easier option to write a GoTo command in both the TRY and CATCH block. If the CATCH block contains a GOTO command, control goes directly to the specified location. This location can work like the "Finally" block and execute the clean up steps.

A sample would look something like this :

try {
    // some code that could be with errors
   GOTO xxx , 'This is the last statement of TRY block
} catch ex {
    //Handle the error
   GOTO XXX
}

XXX
  'your clean up steps
Sachin Verma
  • 351
  • 5
  • 16
  • One of my requirements is to preserve the original exception context from the first THROW. As far as I know, once I do a CATCH (goto or not) and a new THROW, the context will be replaced by the second THROW. One of the main features of a "true" FINALLY block is that it does not affect the original error context. – Chris Smith May 25 '16 at 15:27