Debugging Multithreaded Applications
|
dbx can debug multithreaded applications that use either Solaris threads or POSIX threads. With dbx, you can examine stack traces of each thread, resume all threads, step or next a specific thread, and navigate between threads.
dbx recognizes a multithreaded program by detecting whether it utilizes libthread.so. The program will use libthread.so either by explicitly being compiled with -lthread or -mt, or implicitly by being compiled with -lpthread.
This chapter describes how to find information about and debug threads using the dbx thread commands.
This chapter is organized into the following sections:
Understanding Multithreaded Debugging
When it detects a multithreaded program, dbx tries to load libthread_db.so, a special system library for thread debugging located in /usr/lib.
dbx is synchronous; when any thread or lightweight process (LWP) stops, all other threads and LWPs sympathetically stop. This behavior is sometimes referred to as the "stop the world" model.
Note - For information on multithreaded programming and LWPs, see the Solaris Multithreaded Programming Guide.
|
Thread Information
The following thread information is available in dbx:
(dbx) threads
t@1 a l@1 ?() running in main()
t@2 ?() asleep on 0xef751450 in_swtch()
t@3 b l@2 ?() running in sigwait()
t@4 consumer() asleep on 0x22bb0 in _lwp_sema_wait()
*>t@5 b l@4 consumer() breakpoint in Queue_dequeue()
t@6 b l@5 producer() running in _thread_start()
(dbx)
|
For native code, each line of information is composed of the following:
- The * (asterisk) indicates that an event requiring user attention has occurred in this thread. Usually this is a breakpoint.
An 'o' instead of an asterisk indicates that a dbx internal event has occurred.
- The > (arrow) denotes the current thread.
- t@number, the thread id, refers to a particular thread. The number is the thread_t value passed back by thr_create.
- b l@number or a l@number means the thread is bound to or active on the designated LWP, meaning the thread is actually runnable by the operating system.
- The "Start function" of the thread as passed to thr_create. A ?() means that the start function is not known.
- The thread state (See TABLE 11-1 for descriptions of the thread states.)
- The function that the thread is currently executing.
For Java code, each line of information is composed of the following:
- t@number, a dbx-style thread ID
- The thread state (See TABLE 11-1 for descriptions of the thread states.)
- The thread name in single quotation marks
- A number indicating the thread priority
TABLE 11-1 Thread and LWP States
Thread and LWP States
|
Description
|
suspended
|
The thread has been explicitly suspended.
|
runnable
|
The thread is runnable and is waiting for an LWP as a computational resource.
|
zombie
|
When a detached thread exits (thr_exit)), it is in a zombie state until it has rejoined through the use of thr_join(). THR_DETACHED is a flag specified at thread creation time (thr_create()). A non-detached thread that exits is in a zombie state until it has been reaped.
|
asleep on syncobj
|
Thread is blocked on the given synchronization object. Depending on what level of support libthread and libthread_db provide, syncobj might be as simple as a hexadecimal address or something with more information content.
|
active
|
The thread is active on an LWP, but dbx cannot access the LWP.
|
unknown
|
dbx cannot determine the state.
|
lwpstate
|
A bound or active thread state has the state of the LWP associated with it.
|
running
|
LWP was running but was stopped in synchrony with some other LWP.
|
syscall num
|
LWP stopped on an entry into the given system call #.
|
syscall return num
|
LWP stopped on an exit from the given system call #.
|
job control
|
LWP stopped due to job control.
|
LWP suspended
|
LWP is blocked in the kernel.
|
single stepped
|
LWP has just completed a single step.
|
breakpoint
|
LWP has just hit a breakpoint.
|
fault num
|
LWP has incurred the given fault #.
|
signal name
|
LWP has incurred the given signal.
|
process sync
|
The process to which this LWP belongs has just started executing.
|
LWP death
|
LWP is in the process of exiting.
|
Viewing the Context of Another Thread
To switch the viewing context to another thread, use the thread command. The syntax is:
thread [-blocks] [-blockedby] [-info] [-hide] [-unhide] [-suspend] [-resume] thread_id
|
To display the current thread, type:
To switch to thread thread_id, type:
For more information on the thread command, see thread Command.
Viewing the Threads List
To view the threads list, use the threads command The syntax is:
threads [-all} [-mode [all|filter] [auto|manual]]
|
To print the list of all known threads, type:
To print threads normally not printed (zombies), type:
For an explanation of the threads list, see Thread Information.
For more information on the threads command, see threads Command.
Resuming Execution
Use the cont command to resume program execution. Currently, threads use synchronous breakpoints, so all threads resume execution.
Understanding LWP Information
Normally, you need not be aware of LWPs. There are times, however, when thread level queries cannot be completed. In these cases, use the lwps command to show information about LWPs.
(dbx) lwps
l@1 running in main()
l@2 running in sigwait()
l@3 running in _lwp_sema_wait()
*>l@4 breakpoint in Queue_dequeue()
l@5 running in _thread_start()
(dbx)
|
Each line of the LWP list contains the following:
- The * (asterisk) indicates that an event requiring user attention has occurred in this LWP.
- The arrow denotes the current LWP.
- l@number refers to a particular LWP.
- The next item represents the LWP state.
- in function_name() identifies the function that the LWP is currently executing.
Debugging a Program With dbx
| 817-0923-10
|
|
Copyright © 2003, Sun Microsystems, Inc. All rights reserved.