Topic: Lotus Domino
I typically find that the abilities of LotusScript almost always leave me wanting more. This is particularly true in the area of error handling.
I think most Domino developers follow a fairly typical path when learning to write error handlers.
- what errors?
- on error resume next
- on error goto ErrorHandler
The ErrorHandler typically comprises some number of the following: logging the type of error (err and / or error), where the error occurred (by line number or function name or both), and exiting. And this code in whatever form it takes, must be present in each module. Or so I assumed.
"When I was a child, I spake as a child, I understood as a child, I thought as a child: but when I became a seasoned programmer, I put away childish things."
For a couple of years now we've had lsi_info() and getthreadinfo() to help us provide some additional clues as to where a given error occurred. getthreadinfo() is pretty straightforward as it's actually documented. lsi_info() is where things really start to get interesting.
For example:
- lsi_info(2) - module name where the lsi_info() occurs.
- lsi_info(12) - calling module name where lsi_info() occurs.
- numerous others...
all of the arguments to lsi_info() are undocumented and according to numerous reports are not entirely thread safe. So buyer beware.
I have continued to use these functions in my usual error handling. a little more sophisticated, but ultimately not much better.
It occurred to me after testing some additional arguments to the lsi_info() function that there might be a wholly different and better way to do this.
The key to all of this is lsi_info(14) which provides a stack trace (v6 and later only). Thats right, boys and girls, a stack trace. No more push() ing and pop() ing module names into an array or list to keep track of a given error. Not only that, but since unhandled errors bubble up to the calling functions errorhandler the code to handle fatal errors (you still have to handle your non-fatal ones locally) can be put in only the top level module of a given piece of code (say Initialize for an agent)
It's not a perfect world. You'll need to format the stack trace before you present it to either your log or user.
Function Foobar()
'Error occurs here!
End Function
Sub Initialize()
On Error goto ErrorHandler
Dim errh as New customErrorHandler
call Foobar()
ErrorHandler:
call errh.ReportFatal() 'Gets handled here.
Resume ExitWithError
ExitWithError:
End Sub()