Next: , Previous: , Up: Top   [Index]


Debugging

Error Handling and Debugging

In addition to the process of debugging the internals of the Ctalk front end and libraries, which is described in the Ctalk Language Reference, there are a few classes and methods that programs can use to display diagnostic information when they are run.

ObjectInspector Class

The ObjectInspector class contains methods to print the contents of objects, and an interactive object inspector.

The inspect method is implemented in Object class as a convenience wrapper for the inspect method in ObjectInspector class. That allows you to open an interactive object inspector by sending the message inspect to any object.


int main () {

    String new myStr;

    myStr inspect;

}

Typing ? or help at the inspector’s command prompt displays a brief list of commands. There is a more detail description in the inspect(3ctalk) manual page and in the Ctalk Tools Texinfo manual.

Exception Class

Ctalk’s main error handling class is Exception class. Exception objects contain information about errors so that applications can handle the errors as necessary.

Here again is the method highlightButton from the section, Method Dispatchers. See highlightButtonExample.

List instanceMethod highlightButton (void) {
  Exception new e;
  if (self value is ANSIButtonPane) {
    eval self highlightButton;
  } else {
    e raiseCriticalException INVALID_RECEIVER_X, 
      "Receiver of \"highlightButton\" is not an ANSIButtonPane object";
  }
  return NULL;
}

There are two methods that generate exceptions: raiseException and raiseCriticalException.

The first argument to these methods is the class of the exception, which helps determine how Ctalk should handle the exception. There is a complete list of exception classes in the Exception class section of Ctalk Language Reference. The second argument is text that is provided by the method, and this text is printed when the exception’s message is displayed.

The main difference between raiseException and raiseCriticalException is that exceptions that are generated internally by Ctalk are not treated as critical, and Ctalk handles them automatically. Critical exceptions, however, are generated by methods and applications, and it is up to an application to handle them.

Remember that raising an exception only records information about the error condition. To report the error condition, Exception class provides the pending and handle methods, which provide basic error notification and reporting. Here a code segment that shows a simple way to handle an exception.

int main () {
   Exception new myException;

   do something... 

  if (myException pending)
    myException handle;
}

If some previous operation raised an exception, then the myException handle deals with the error, generally, but not always, by printing an error message on the terminal.

System Errors and SystemErrnoException Class

When programming with C, it is often necessary errors generated by C functions. This procedure is so common that these error conditions have their own class, SystemErrnoException. The SystemErrnoException class simply translates an error as reported by the C library into a Ctalk exception.

SystemErrnoException objects work similarly to Exception objects, but instead of providing an exception class as an argument, SystemErrnoException objects record the type of error automatically using the C library’s error code. When handling a SystemErrnoException, the error report is composed of the system’s text for that error code, and also the text provided by the application when the exception is raised.

Here is an example of a SystemErrnoException object. This example is part of the openOn method from class ReadFileStream.

SystemErrnoException new __errnoException;

...

if ((f = fopen (__streamPathName, "r")) != NULL) {
  __ctalkObjValPtr (selfval, f);
  self streamPath = __streamPathName;
  self statStream;
} else {
  __errnoException raiseException __streamPathName;
}

SystemErrnoException objects are always treated as critical exceptions, so it is up to the application to handle them by using the pending and handle methods as described in the previous section.

Printing Call Sequences for Exceptions

While exceptions are convenient for recording error conditions, reporting an error later can also make it difficult to determine exactly where or when in the program the error occurred. For this reason, exceptions also record the program’s call stack at the time the exception occurred.

The method enableExceptionTrace in class Object enables the printing of the program’s call stack to the console’s standard error channel when a program deals with an exception using handle (class Exception).

A program can turn off the display of the call stack with the disableExceptionTrace method, also in class Object. The method traceEnabled in class Object returns TRUE or FALSE depending on whether call stack displays are enabled.

A program can print an exception’s call stack using printExceptionTrace in class Exception. Here is the code from the handle method that calls printExceptionTrace.

if (self traceEnabled) {
  self printExceptionTrace;
}

Application Specific Exception Handlers

Sometimes simply printing an error message to the terminal is not useful, so Exception class allows you to define application specific exception handlers.

When handling exceptions, Ctalk handles the Exception object using the highest-level handler that is installed by the application, or the default handler otherwise.

Briefly, custom exception handlers are Method objects that are defined by an application and implemented in Exception class. Applications use the installHandler method, also from Exception class, to install them.

There is an example of an application specific exception handler in the Exception class section of the Ctalk Language Reference, as well as a discussion of how an application might handle exceptions.

One common use of custom handlers is a Web CGI program. Simply outputting error messages to the terminal does not provide any useful information; instead, using a custom exception handler, the application can print error messages in the Web browser window.

Here is the exception handler from the wiki.c example program.

Exception instanceMethod errorToBrowser (void) {
  String new msg;
  wikiApp httpHeader;
  wikiApp htmlPageHeader "Ctalk Wiki | Error";
  wikiApp outputString "<h2>Ctalk Wiki Error:</h2>";
  msg = __ctalkPeekExceptionTrace ();
  wikiApp outputString "<pre>" + msg + "</pre><br>";
  msg = __ctalkPeekRunTimeException ();
  wikiApp outputString "<pre>" + msg + "</pre>";
  wikiApp outputString "Please contact your system adminstrator or " + 
    "the Ctalk language project at rk3314042@gmail.com.";
  error = TRUE;
  return NULL;
}

Then, when the application is run, it installs the handler using statements like these.

Exception new postDataException;
...
postDataException installHandler "errorToBrowser";

Examining Objects with Inspectors

Ctalk provides a basic set of methods that can inspect and print the contents of objects.

The inspect method in Object class is an interactive utility that lets you examine a program’s objects as the program is running.

To inspect an object, simply send it the message, inspect - it’s a shortcut for the inspect method in ObjectInspector class, which a program can also call directly.


String new globalString;

int main () {
  Integer new i;

  globalString = "global string";

  i inspect;
}

In either case, the program stops execution when it reaches the inspect method, and presents a prompt where you can type commands.

Here’s a transcript of a brief inspector session.


$ ./inspect 
> p
p
name:       i
class:      Integer (0x48bf4958)
superclass: Magnitude (0x48bf29f0)
value:      (null) (Integer)

> p g globalString
p g globalString
name:       globalString
class:      String (0x48cce8d0)
superclass: Character (0x48c8acc0)
value:      global string (String)

> c
c
$ 

At the inspector prompt, ‘> ’, the command ‘p’ prints the inspector’s receiver object, and ‘p g globalString’ prints the named global object, globalString. The ‘c’ command exits the inspector and continues running the program.

There are several commands that the inspector recognizes. Typing ‘?,’ ‘h,’ or ‘help’ at the prompt displays a list of them.

The inspector uses the method formatObject to print the contents of individual objects.

If you want to print a formatted object directly, without stopping the program, Ctalk also has the method dump in Object class, which simply calls formatObject with its receiver object to print the object and then returns so the program can continue running.

You can also debug Ctalk apps (and Ctalk itself) at the source code level with the GNU gdb debugger. This requires that you build Ctalk and/or its application programs with the source information. Refer to the “Debugging” section of the Ctalk Language Reference for more information.

Exit Handlers and Error Tracing

Ctalk provides two C handlers that you can use for debugging, installExitHandlerBasic and installAbortHandlerBasic. They are written in C and are more robust, though less flexible, than signal handlers written using SignalHandler objects.

These signal handlers provide basic cleanup of the class dictionaries before exiting, and, if stack tracing is enabled, optionally print a stack trace of where the program was executing when the signal occurred.

For example, to enable the handlers with stack tracing, you could use the following code.

Application new myApp;
Object new anyObject;
...
anyObject enableExceptionTrace;
myApp installExitHandlerBasic;
myApp installAbortHandlerBasic;

The enableExceptionTrace method is defined in class Object, so you can send the message to any object in a program to enable exception tracing.

The installExitHandlerBasic method provides a handler that exits a program neatly when the user presses C-c in a UNIX terminal or C-break in a DJGPP text window.

The installAbortHandlerBasic method is useful for printing traces when a system library detects an error.

If the application enables exception tracing, these methods print a stack trace from the point where a signal is received before causing the application to exit.

It is relatively easy to write handlers for whatever signals a program needs to catch. The methods in the Application and SignalHandler classes should provide a starting point for writing application-specific handlers. Also, you might want to look at timeclient.c and timesignal.c in the demos subdirectory of the Ctalk distribution.


Next: , Previous: , Up: Top   [Index]