包含在查找更多文档专项支持资源 | 以 PDF 格式下载本书 (2099 KB)
Chapter 11 Debugging Multithreaded Applicationsdbx 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 uses 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 DebuggingWhen 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 InformationThe following thread information is available in dbx:
For native code, each line of information is composed of the following:
For Java code, each line of information is composed of the following:
Viewing the Context of Another ThreadTo switch the viewing context to another thread, use the thread command. The syntax is:
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 ListTo view the threads list, use the threads command. The syntax is:
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 ExecutionUse the cont command to resume program execution. Currently, threads use synchronous breakpoints, so all threads resume execution. However, you can resume a single thread using the call command with the -resumeone option (see call Command). Consider the following two scenarios when debugging a multithreaded application where many threads call the function lookup():
When calling strcmp(), dbx would resume all threads for the duration of the call, which similar to what dbx does when you are single stepping with the next command. It does so because resuming only t@1 has the potential to cause a deadlock if strcmp() tries to grab a lock that is owned by another thread. A drawback to resuming all threads in this case is that dbx cannot handle another thread, such as t@2, hitting the breakpoint at lookup() whilestrcmp() is being called. It emits a warning like one of the following: event infinite loop causes missed events in following handlers: Event reentrancy first event BPT(VID 6, TID 6, PC echo+0x8) second event BPT(VID 10, TID 10, PC echo+0x8) the following handlers will miss events: In such cases, if you can ascertain that the function called in the conditional expression will not grab a mutex, you can use the -resumeone event modifier to force dbx to resume only t@1:
Only the thread that hit the breakpoint in lookup() would be resumed in order to evaluate strcmp(). This approach does not help in cases such as the following:
Understanding Thread Creation ActivityYou can get an idea of how often your application creates and destroys threads by using the thr_create event and thr_exit event as in the following example:
The application created three threads. Note how the threads exited in reverse order from their creation, which might indicate that had the application had more threads, the threads would accumulate and consume resources. To get more interesting information, you could try the following in a different session:
The output shows that all three threads were created by thread t@1, which is a common multi-threading pattern. Suppose you want to debug thread t@3 from its outset. You could stop the application at the point that thread t@3 is created as follows:
If your application occasionally spawns a new thread from thread t@5 instead of thread t@1, you could capture that event as follows:
Understanding LWP InformationNormally, 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.
Each line of the LWP list contains the following:
Use thelwp Command to list or change the current LWP. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||