HPlogo HP/DDE Debugger User's Guide: HP 9000 Series 700/800 Computers > Chapter 8 Debugging in Special Situations

Debugging Multi-Threaded Applications

» 

Technical documentation

Complete book in PDF

 » Table of Contents

 » Glossary

 » Index

HP/DDE supports the debugging of multi-threaded applications that are implemented with HP DCE threads. (The Softbench version of the debugger for Solaris systems supports Solaris Threads.)

HP/DDE thread support includes:

  • A Threads dialog box for monitoring, examining, and manipulating threads

  • Support for setting breakpoints on specific threads in the Breakpoint Set/Change dialog box

  • A thread_id identifier that allows specification of individual threads

  • A thread component added to the debugger's concept of environment

  • Thread-specific commands and options

You can prepare and invoke a multi-threaded application for debugging like any other target program. See “Preparing the Target Program” for more information on preparing and invoking target programs for debugging.

Multi-threaded applications may execute quite differently when they are invoked by the debugger because the debugger takes control of the thread scheduler. Some debugger commands, like step and thread -select, override the thread scheduler.

See Programming With Threads on HP-UX for more information about HP DCE threads.

Making libdce.sl Writable

If your application uses /usr/lib/libdce.sl (the shared library version of HP DCE threads), you must make the shared library writable before you debug the application.

The following command maps all shared libraries as writable:

property flags tgt_shlib_debug

You can place the command in your .dderc file. You can also invoke it from the debugger command line before you issue the debug command.

When libdce.sl is read-only, you cannot step into routines or set breakpoints in them. Also, some thread-related debugger commands will not work. The affected commands are:

intercept thread_create
intercept thread_exit
intercept thread_switch
thread

If libdce.sl is read-only and you attempt to use one of the commands listed above, the debugger will display a not mapped writable message.

Stripped and Unstripped Versions of libdce.sl

If your application links in an unstripped version of /usr/lib/libdce.sl, all threads-related commands and options will work properly.

If, however, your program links in a stripped version of /usr/lib/libdce.sl, the threads-related commands and options will behave as if your program had only one thread.

Use the nm command to determine if your system has a stripped version of libdce.sl. The output of nm contains a no symbols message when libdce.sl is stripped. For example:

$ nm /usr/lib/libdce.sl   nm:  /usr/lib/libdce.sl:  no symbols

If libdce.sl is stripped, link your program with the archive library /usr/lib/libdce.a in order to debug it.

Viewing and Manipulating Threads

Choose Execution:Threads to display the Threads dialog box. The Threads dialog box, shown in Figure 8-1 “The Threads Dialog Box ”, displays a list of threads in your program. The list is automatically updated as threads are created or change status.

Figure 8-1 The Threads Dialog Box

[The Threads Dialog Box]

Notice the following in the thread list:

  • A numeric thread identifier is displayed for each thread. The thread number is assigned by the debugger.

    Thread 1 is the initial thread (also known as the distinguished thread) and Thread 2 is the system thread. The debugger always assigns the first two identifiers to these threads.

    You can use these numeric identifiers for commands that require a thread_id (for example, breakpoint -thread thread_id).

  • Threads are also labeled by the initial procedure name. In this case, the initial procedure name was thread.

  • Thread status is indicated with the labels RUNNING, READY, BLOCKED, and TERMINATED. Note that execution of TERMINATED threads has ended but the thread itself has not yet been deleted.

  • The point where execution has stopped is indicated with the -> marker.

You can also use the list threads command to display a list similar to the one in the Threads dialog box.

When you highlight one or more threads in the Threads dialog box, you can select a button to request the following actions:

Disable

Remove the selected thread(s) from the list of threads that can run when the program is resumed.

Enable

Add the selected thread(s) to the list of threads that can run when the program is resumed.

Kill

Kill the selected thread(s).

Stack Trace...

Display the selected thread's call/return stack in a new window.

To monitor the call/return stack of each thread as it executes, invoke the Stack View dialog box by selecting Show:Stack from the menu bar.

-> Next to Run

Make the selected thread the current execution thread. This thread will be the first to run when the program is resumed.

Examine

Change environment to the selected thread. This allows you to examine the status of a thread without changing the current Execution thread.

Setting Breakpoints on Threads

You can activate breakpoints on all threads, or on any selected set of threads.

The Breakpoints Set/Change dialog box contains an area at the bottom which allows you select which threads the breakpoint will be set on. Choose Break:Set to invoke the Breakpoints Set/Change dialog box.

Also, the breakpoint command has a -thread option. See the online command reference for more information and examples.

Environment in Multi-Threaded Applications

When the target program is multi-threaded, the debugger includes a thread component in its concept of environment. (See Chapter 7 “Identifying Program Objects ” for more information on the debugger's general concept of environment.)

For example, the following shows the output from a list environment command during a debugging session on a multi-threaded target program:

list environment
Stopped at: \\file_copy\worker\222 (`thread(3))

Notice the output indicates that the current environment is in Thread 3.

It is useful to invoke the Stack View dialog box when debugging multi-threaded programs. You can invoke it by selecting Show:Stack from the menu bar.

Figure 8-2 Stack View Dialog Box Showing Current Thread

[Stack View Dialog Box Showing Current Thread]

As shown in Figure 8-2 “Stack View Dialog Box Showing Current Thread ”, the Stack View dialog box shows the call/return stack for the current thread. The current thread is the thread that the debugger refers to when evaluating expressions. It differs from the running thread when you change environment from one thread to another. For example, you can use the thread specifier, `thread(n) to change the current thread, in the following context:

environment `thread(3)

Notice that the call/return stack in multi-threaded applications includes a number of system calls. In Figure 8-2 “Stack View Dialog Box Showing Current Thread ”, the system call names begin with the cma__ prefix.

Arrow buttons in the Stack View dialog box allow you to move up and down the call/return stack within the current thread. You can also use the frame specifiers described in Chapter 7 “Identifying Program Objects ” (`env, `run, and `main). The command environment `env(-1), for example, moves to the caller of the current frame without changing the current thread.

In addition, you can combine thread specifiers with frame specifiers to write fully qualified environment specifiers. The following shows the syntax for fully qualified environment specifiers:

`thread(thread_id)\`main(frame_number)
`thread(thread_id)\`run(frame_number)
`thread(thread_id)\`env(+|-n)

The `thread(thread_id) notation may also be used wherever another environment qualifier can be used. The command print `thread(5)\x, for example, prints the variable x in the environment of the run frame of Thread 5.

Thread-Specific Debugger Commands

The two commands that apply specifically to debugging threaded applications are list threads and thread.

Use the list threads command to obtain a list of thread identifiers for a target program. You can also use the Threads dialog box which is described in “Viewing and Manipulating Threads”.

The thread command changes the state of program threads. The following briefly describes the thread command with its options:

  • thread -select alters the scheduler so that the specified thread runs when the program executes. This option is similar to the goto command in that it alters the point of execution of the program. The debugger cannot ensure that the program state is valid following this transfer of control.

    The selected thread is the only one operated on by a step command.

  • thread -disable prevents specified threads from running until they are enabled again using thread -enable.

  • thread -enable allows the specified thread to run when you issue a go command. By default, all threads are enabled; ordinarily you use thread -enable to reactivate a disabled thread.

  • thread -kill marks the specified thread for termination. The killed thread persists until the thread scheduler actually terminates it.

In addition, the intercept command can take the following arguments when you are debugging multi-threaded applications:

thread_create

Stops program execution when a thread is created.

thread_exit

Stops program execution when a thread is terminated.

thread_switch

Stops program execution when the context changes from one thread to another.

Finally, some debugger commands allow you to specify a thread by using the -thread option. Those commands are:

activate breakpoints
breakpoint
delete breakpoints
suspend breakpoints
tb

For more information on the commands described in this section, see the online command reference.