Debugging NetCF apps using CorDbg - Part X: Threads

Earlier in this series, I mentioned I would talk a bit about threads...

Commands
re[sume]
su[spend]
t[hreads]

Working with threads in CorDbg is pretty straight forward.  The viewing an navigating of your application's threads is done using the t[hreads] command.  To display a list of threads, use the t[hreads] command without any arguments.

Note: In this and in all subsequent thread listings, I have trimmed the data to reduce post length and to, I hope, improve readability.  I have used <...> to indicate the modifications.

(cordbg) t
*Thread 0x21ef84 R 0)* WebCrawler!WebCrawler.Crawler::Crawl +0000[IL] in <path>\Crawler.cs:343

 Thread 0x416d4 R 0)  <...>
2)  WebCrawler!WebCrawler.MainForm::Main +000a[IL] in <path>\mainform.cs:256

The above example shows an application with two threads.  By looking at the output from the t[hreads] command, you can see that both of the threads are running code (shown by the R designation).  You can also see the call stack for each thread.

To switch thread contexts, simply add the desired thread's identifier (the number displayed in hex) to the t[hreads] command.

(cordbg) t 0x416d4
Thread 0x416d4 R 0)* <...>
2)  WebCrawler!WebCrawler.MainForm::Main +000a[IL] in <path>\mainform.cs:256

You can now browse that thread's source (after walking up the stack to get to the application's frame).

(cordbg) u 2
256:            }
(cordbg) sh
251:            /// The main entry point for the application.
252:            /// </summary>
253:            static void Main()
254:            {
255:             Application.Run(new MainForm());
256:*           }

At times, you may need to stop a thread while debugging.  Perhaps it interacts with the code you are examining, or is modifying a resource (ex: file) that you need in to be left untouched.

You can pause a thread using the su[spend] command.

(cordbg) su 0x416d4
Will suspend thread 0x416d4.

To verify that the thread did, indeed, get suspended, re-issue the t[hreads] command.

(cordbg) t
 Thread 0x21ef84 R 0)  WebCrawler!WebCrawler.Crawler::Crawl +0000[IL] in <path>\Crawler.cs:343

*Thread 0x416d4 S 0)  <...>
2)* WebCrawler!WebCrawler.MainForm::Main +000a[IL] in <path>\mainform.cs:256

You will notice that the suspended thread is now marked with an S (for suspended).  Your target thread is paused, and will not resume execution unless instructed to by the re[sume] command.

(cordbg) re 0x416d4
Will resume thread 0x416d4.
(cordbg) t
 Thread 0x21ef84 R 0)  WebCrawler!WebCrawler.Crawler::Crawl +0000[IL] in <path>\Crawler.cs:343

*Thread 0x416d4 R 0)  <...>
2)* WebCrawler!WebCrawler.MainForm::Main +000a[IL] in <path>\mainform.cs:256

It is important to note that when you suspend a thread, you should also remember to resume it when you are finished debugging.  If you continue your application (g[o] -or- cont) without resuming threads suspended during debugging, they will remain "asleep", blocking any other threads that may be waiting on them.

If you find yourself in such a situation, you can break into the debugger (ctrl+break), display the application's threads and check to see if any are suspended.  If so, resume the suspended thread(s) and continue your application.  Any threads blocked on the newly awakened thread will unblock and your application will run normally again.

Note: The examples shown above were created using NetCF v1 SP2, the WebCrawler sample (shipped with Microsoft Visual Studio .NET 2003 - \Program Files\Microsoft Visual Studio .NET 2003\CompactFrameworkSDK\v1.0.5000\Windows CE\Samples\VC#\Pocket PC\WebCrawler) and cordbg.exe (version 1.1.4322.573).

Enjoy!
-- DK

[Edit: Cleanup commands list]
[Edit: Fix minor error]

Disclaimer(s):
This posting is provided "AS IS" with no warranties, and confers no rights.