HP OpenVMS Systems Documentation |
OpenVMS Debugger Manual
17.6.3 Setting Breakpoints on Ada Task Bodies, Entry Calls, and Accept StatementsYou can set a breakpoint on a task body by using one of the following syntaxes to refer to the task body (see Section 17.3.2):
For example, the following command sets a breakpoint on the body of task CHILD. This breakpoint is triggered just before the elaboration of the task's declarative part (also called the task's activation).
CHILD$TASK_BODY is a name for the address of the first instruction the task will execute. It is meaningful to set a breakpoint on an instruction, and hence on this name. However, you must not name the task object (for example, CHILD) in a SET BREAK command. The task-object name designates the address of a data item (the task value). Just as it is erroneous to set a breakpoint on an integer object, it is erroneous to set a breakpoint on a task object. You can monitor the execution of communicating tasks by setting breakpoints or tracepoints on entry calls and accept statements.
There are several points in and around an accept statement where you might want to set a breakpoint or tracepoint. For example, consider the following program segment, which has two accept statements for the same entry, RENDEZVOUS:
You can set a breakpoint or tracepoint in the following places in this example:
To set a breakpoint or tracepoint in and around an accept statement, you can specify the associated line number. For example, the following command sets a breakpoint on the start and also on the body of the first accept statement in the preceding example:
To set a breakpoint or a tracepoint on an accept statement body, you can also use the entry name (specifying its expanded name to identify the task body where the entry is declared). For example:
If there is more than one accept statement for an entry, the debugger treats the entry as an overloaded name. The debugger issues a message indicating that the symbol is overloaded, and you must use the SHOW SYMBOL command to identify the overloaded names that have been assigned by the debugger. For example:
Overloaded names have an integer suffix preceded by two underscores. For more information on overloaded names, see the debugger's online help (type Help Language_Support Ada). To determine which of these overloaded names is associated with a particular accept statement, use the EXAMINE/SOURCE command. For example:
In the following example, when the breakpoint triggers, the caller task is evaluated (see Section 17.3.4 for information about the symbol %CALLER_TASK):
The following breakpoint triggers only when the caller task is %TASK 2:
If the calling task has more than one entry call to the same accept statement, you can use the SHOW TASK/CALLS command to identify the source line where the entry call was issued. For example:
17.6.4 Monitoring Task EventsThe SET BREAK/EVENT and SET TRACE/EVENT commands enable you to set breakpoints and tracepoints that are triggered by task and exception events. For example, the following command sets tracepoints that trigger whenever task CHILD or %TASK 2 makes a transition to the RUN state:
When a breakpoint or tracepoint is triggered as a result of an event, the debugger identifies the event and gives additional information. The following tables list the event-name keywords that you can specify with the SET BREAK/EVENT and SET TRACE/EVENT commands:
1 An unhandled exception is an exception for which there is no handler in the current frame or for which there is a handler that executes a raise statement and propagates the exception to an outer scope. In the previous tables, the exception-related events are included for completeness. Only the task events are discussed in the following paragraphs. For more information about the exception events, see the debugger's online help (type Help Language_Support Ada). You can abbreviate an event-name keyword to the minimum number of characters that make it unique. The event-name keywords that you can specify with the SET BREAK/EVENT or SET TRACE/EVENT command depend on the current event facility, which is either THREADS or ADA in the case of task events. The appropriate event facility is set automatically when the program is brought under debugger control. The SHOW EVENT_FACILITY command identifies the facility that is currently set and lists the valid event name keywords for that facility (including those for the generic events). Several examples follow showing the use of the /EVENT qualifier:
The following predefined event breakpoints are set automatically when the program is brought under debugger control:
Ada examples of the predefined and other types of event breakpoints follow.
Example of EXCEPTION_TERMINATED Event
When the EXCEPTION_TERMINATED event is triggered, it usually indicates an unanticipated program error. For example:
Example of DEPENDENTS_EXCEPTION Event (Ada)
For Ada programs, the DEPENDENTS_EXCEPTION event often unexpectedly precedes a deadlock. For example:
Example of RENDEZVOUS_EXCEPTION Event (Ada)
For Ada programs, the RENDEZVOUS_EXCEPTION event enables you to see an exception before it leaves a rendezvous (before exception information has been lost due to copying the exception into the calling task). For example:
To cancel breakpoints (or tracepoints) set with the /EVENT qualifier, use the CANCEL BREAK/EVENT (or CANCEL TRACE/EVENT) command. Specify the event qualifier and optional task expression in the CANCEL command exactly as you did with the SET command, excluding any WHEN or DO clauses. You might want to set event breakpoints and tracepoints in a debugger initialization file for your tasking programs. For example:
17.7 Additional Task-Debugging TopicsThe following sections discuss additional topics related to task debugging:
17.7.1 Debugging Programs with Deadlock ConditionsA deadlock is an error condition in which each task in a group of tasks is suspended and no task in the group can resume execution until some other task in the group executes. Deadlock is a typical error in tasking programs (in much the same way that infinite loops are typical errors in programs that use WHILE statements). A deadlock is easy to detect: it causes your program to appear to suspend, or hang, in midexecution. When deadlock occurs in a program that is running under debugger control, press Ctrl/C to interrupt the deadlock and display the debugger prompt. In general, the SHOW TASK/ALL command (see Section 17.4) or the SHOW TASK/STATE=SUSPENDED command is useful because it shows which tasks are suspended in your program and why. The command SET TASK/VISIBLE %NEXT_TASK is particularly useful when debugging in screen mode. It enables you to cycle through all tasks and display the code that each task is executing, including the code in which execution is stopped. The SHOW TASK/FULL command gives detailed task state information, including information about rendezvous, entry calls, and entry index values. The SET BREAK/EVENT or SET TRACE/EVENT command (see Section 17.6.4) enables you to set breakpoints or tracepoints at or near locations that might lead to deadlock. The SET TASK/PRIORITY and SET TASK/RESTORE commands enable you to see if a low-priority task that never runs is causing the deadlock. Table 17-9 lists a number of tasking deadlock conditions and suggests debugger commands that are useful in diagnosing the cause.
17.7.2 Automatic Stack Checking in the DebuggerIn tasking programs, an undetected stack overflow can occur in certain circumstances and can lead to unpredictable execution. (For more information on task stack overflow, see the Compaq Ada or POSIX Threads documentation.) The debugger automatically does the following stack checks to help you detect the source of stack overflow problems (if the stack pointer is out of bounds, the debugger displays an error message):
The following examples show the kinds of error messages displayed by the debugger when a stack check fails. A warning is issued when most of the stack has been used up, even if the stack has not yet overflowed.
One of the unpredictable events that can happen after a stack overflows is that the stack can then underflow. For example, if a task stack overflows and the stack pointer remains in the top guard area, the operating system will attempt to signal an ACCVIO condition. However, because the top guard area is not a writable area of the stack, the operating system cannot write the signal arguments for the ACCVIO. When this happens, the operating system cuts back the stack: it causes the frame pointer and stack pointer to point to the base of the main program stack area, writes the signal arguments, and then modifies the program counter to force an image exit.
If a time-slice AST or other AST occurs at this instant, execution can
resume in a different task, and for a while, the program may continue
to execute, although not normally (the task whose stack overflowed may
use---and overwrite---the main program stack). The debugger stack
checks help you to detect this situation. If you step into a task whose
stack has been cut back by the operating system, or if you use the SHOW
TASK/ALL command at that time, the debugger issues its stack underflow
message.
Pressing Ctrl/C is the recommended method of interrupting program execution or a debugger command during a debugging session. This returns control to the debugger; pressing Ctrl/Y returns control to DCL level. If you interrupt a task debugging session by pressing Ctrl/Y, you might have some problems when you then start the debugger at DCL level with the DEBUG command. In such cases, you should insert the following two lines in the source code at the beginning of your main program to name the Compaq Ada predefined package CONTROL_C_INTERCEPTION:
For information on this package, see the Compaq Ada documentation.
|