Fanning Software Consulting

Error Handling in iTools

QUESTION: Is the error handling mechanism in iTools a bit cryptic? When I get an error in one of my programs a little dialog box pops up with an error message, but the message is often not very helpful. Sometimes it gives me a clue about what the problem might be, but there are no line numbers or program module names or anything that helps me solve the problem. Yesterday I spent three hours puzzling about a problem that in the end turned out to be the iTool module catching and handling an error silently for goodness sake! Is there any way to improve the error handling so I can figure out what is going on?

ANSWER: Yes, I agree that the error handling can be improved in the iTool system. It can be incredibly fustrating to fix code if you don't know where (or why) it is broken. But you want to be very, very careful about making changes to code RSI has written. Make sure you have saved a backup copy before you do so.

I've solved the error message problem for myself by adding a few lines of code to the IDLitIMessaging object, defined in the idlitimessaging__define.pro file. The file will be found in the .../lib/itools/framework sub-directory. The code gives me a traceback of the error propagation pathway, including line numbers, so I know exactly what the error is and where it occurred.

Find the ErrorMessage method in this program file. Near the end of that method (on or about line 273 in my file), you will see this code:

   ;; fill in a prompt object and send it to the UI
   oMsg = obj_new("IDLitError", description=strMessage, $
                  message=title, severity=severity)

   iStatus = self.__oTool->SendMessageToUI(oMsg)
   obj_destroy, oMsg

Immediately after this code, insert the following lines of code.

   ; Add this code to get better error handling in iTools!
   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   IF severity GT 1 THEN BEGIN

      ; Get the call stack and the calling routine's name, then print
      ; a traceback message.

      Help, Calls=callStack
      callingRoutine = (StrSplit(StrCompress(callStack[1])," ", /Extract))[0]
      Help, /Last_Message, Output=traceback
      Print,''
      Print, 'Traceback Report from ' + StrUpCase(callingRoutine) + ':'
      Print, ''
      FOR j=0,N_Elements(traceback)-1 DO Print, " " + traceback[j]

   ENDIF
   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Now when an error occurs, you will find an error traceback in your command log window.

   Traceback Report from IDLITSYSTEM::CREATETOOL:

    % Unable to invoke method on NULL object reference: <OBJREF   (<NullObject>)$GT.
    % Execution halted at:  IDLITVISPLOT::SETPROPERTY  650 
   H:\RSI\IDL60\lib\itools\components\idlitvisplot__define.pro
    %                       IDLITOPSETPROPERTY::_DOSETPROPERTY   82          
   H:\RSI\IDL60\LIB\ITOOLS\framework\idlitopsetproperty__define.pro
    %                       IDLITOPSETPROPERTY::_EXECUTEONTARGET  187    
   H:\RSI\IDL60\LIB\ITOOLS\framework\idlitopsetproperty__define.pro
    %                       IDLITOPSETPROPERTY::DOSETPROPERTYWITH_EXTRA  289 
   H:\RSI\IDL60\LIB\ITOOLS\framework\idlitopsetproperty__define.pro
    %                       IDLITSRVCREATEVISUALIZATION::_APPLYPROPERTIES  377 
   H:\RSI\IDL60\LIB\ITOOLS\framework\idlitsrvcreatevisualization__define.pro
    %                       IDLITSRVCREATEVISUALIZATION::_CREATE  307 
   H:\RSI\IDL60\LIB\ITOOLS\framework\idlitsrvcreatevisualization__define.pro
    %                       IDLITSRVCREATEVISUALIZATION::CREATEVISUALIZATION  736    
   H:\RSI\IDL60\LIB\ITOOLS\framework\idlitsrvcreatevisualization__define.pro
    % IDLITSYSTEM::CREATEVISUALIZATION 2041 H:\RSI\IDL60\LIB\ITOOLS\framework\idlitsystem__define.pro
    % IDLITSYSTEM::CREATETOOL 1985 H:\RSI\IDL60\LIB\ITOOLS\framework\idlitsystem__define.pro
    % IDLITSYS_CREATETOOL  130 H:\RSI\IDL60\LIB\ITOOLS\framework\idlitsys_createtool.pro
    % IPLOT             316 H:\RSI\IDL60\LIB\ITOOLS\iplot.pro
    %     $MAIN$          

The advantage of handling the error this way, rather than turning off the CATCH in the idlit_catch.pro file as RSI recommends, is that the program continues to run. Most of the time you can fix the error on the fly, as it were, without having to start over from scratch after every fix.

As always when you work on IDL-supplied code, be sure to keep a copy of the original file in a safe place and write your documentation changes down. You may well have to apply them again in future updates of the software. :-)

Google
 
Web Coyote's Guide to IDL Programming