DCSIMG
October 2009 - Posts - All Your Base Are Belong To Us

All Your Base Are Belong To Us

Mostly .NET internals and other kinds of gory details

October 2009 - Posts

Attach a Debugger When a Process Starts

You can ask Windows to launch another process (typically a debugger) when launching a process of your choice.

One use of this feature is to configure Calculator to launch whenever you launch Notepad, or configure Excel to launch whenever you launch Word. This is a great way to drive a colleague crazy.

Another use of this feature is to attach a debugger to the startup sequence of a process that can’t be easily started from within the debugger. For example, if you’re debugging the startup of a Windows service, you can’t start it from the debugger; the same applies to dllhost.exe processes in a COM+ environment; and there are other examples.

All you need to do to configure this feature is the Global Flags application available with the Debugging Tools for Windows package. In the Image File tab, input the executable name (including the extension) and hit Tab to refresh, and then check the Debugger checkbox and input the name of the debugger to launch. Finally, click Apply—no system restart is required.

There’s no dark debugger magic involved—when Windows launches the ‘target’ process, it checks the registry for the appropriate flag and if it’s present, it will launch the specified process, pass to it the ‘target’ executable name as the first command line parameter, followed by the rest of the original command line arguments.

For example, to configure Calculator to launch whenever you launch Notepad:

image

A more useful example, where you configure the Visual Studio debugger to launch when you launch MyApp.exe:

image

Wait Chain Traversal Debugging Extension for WinDbg

Wait Chain Traversal is a set of APIs introduced in Windows Vista that can be used to display diagnostic information about the wait chains of application threads.

A wait chain is an alternating sequence of THREAD, RESOURCE nodes where a THREAD element describes a thread that holds an instance of a resource and a RESOURCE element describes a resource that a thread waits for.

For example, the sequence T1 –> M1 –> T2 –> M2 –> T1 (where T1, T2 are threads and M1, M2 are mutex objects) describes a classic deadlock because effectively T1 is waiting for itself.

Unfortunately, there is no direct way to display this diagnostic information within the debugger. Therefore, I set forth to write a debugger extension for WinDbg, called wct.dll, that exposes wait chain information about threads and processes on the system. (Writing a debugger extension is a great deal of fun, and I strongly recommend it! :-))

Its syntax is very simple:

Wait Chain Traversal (WCT) debugging extension.
    By Sasha Goldshtein, tinyurl.com/sasha.
This debugging extension displays WCT information.
Syntax:
!wct                       Displays WCT information for the entire system.
!wct_proc [<ProcessID>]    Displays WCT information for the specified
                           process ID or for the current process.
!wct_thread [<ThreadID>]   Displays WCT information for the specified thread
                           ID or for the current thread.

Here’s some sample output from a test application that deadlocks on two mutex objects:

0:001> .load D:\Development\DebuggingExtensions\Release\wct.dll
0:001> !wct_thread
>>> Begin wait chain for thread 4784:6016 with 5 nodes
    Thread [4784:6016:blocked WT=7287568] ==>
    Mutex [\Sessions\1\BaseNamedObjects\SecondMutex] ==>
    Thread [4784:5924:blocked WT=7286947] ==>
    Mutex [\Sessions\1\BaseNamedObjects\FirstMutex] ==>
    Thread [4784:6016:blocked WT=7287568] ==>
DEADLOCK FOUND
>>> End wait chain for thread 4784:6016

In the above output, you see a wait chain for thread 6016 in process 4784. The chain begins with the thread itself which is blocked (WT stands for waiting time and indicates for how long the thread has been blocked). Next, you see the mutex (called “SecondMutex”) that the thread is trying to acquire, which is in turn owned by thread 5924 (of the same process). However, that very thread waits for another mutex (called “FirstMutex”) that is owned by thread 6016, which is right where we started—therefore, we have a deadlock.

You can download this extension from my Debugging Extensions project on CodePlex, where it is available with the source code. (Direct link to the release: x86, x64, updated to require Visual C++ 2008 runtime, see below.)

[Update 10/25: The original download links pointed to the DLL versions that might require the Visual C++ 2010 runtime. I added a Visual Studio 2008 solution to the source control and added download links to DLLs that certainly require only the Visual C++ 2008 runtime (x86, x64). Here is the full set of links: VS2010_x86, VS2010_x64, VS2008_x86, VS2008_x64. If you need a version that works with the Visual C++ 2005 runtime, feel free to compile one directly from the source.]

Template Template Parameters

Here’s a good interview question or riddle for seasoned C++ developers. You’re asked to design a set of template functions for automatic conversion of data from one type to another.

First of all, you’re expected to have a function called scalar_convert<T> for converting values of type T to values of another type that depends on T. Part of the assignment is to come up with a mapping between T and the target type without requiring the caller to pass it along as a template parameter.

Next, you’re expected to have a function called vector_convert for converting containers of element type T to the same container of another element type that would be produced by calling scalar_convert<T> on the container’s elements. This method should work not only with std::vector, but with any push_back style container in the STL (e.g. std::list but not std::set).

The first challenge is relatively easy to address. You write a template function that does nothing, and then specialize it for each conversion. To deduce the target type of the conversion, you can use an auxiliary structure that is also specialized for each T, as follows:

template <typename T>
struct convert_traits { typedef T to_type; };

template <>
struct convert_traits<int> { typedef double to_type; };

template <>
struct convert_traits<double> { typedef int to_type; };

Next, you can define scalar_convert<T>’s return value in terms of convert_traits:

template <typename In>
typename convert_traits<In>::to_type scalar_convert(const In&) { return convert_traits<In>::to_type(); }

template <> int scalar_convert<double>(const double& d) { return (int)d; }
template <> double scalar_convert<int>(const int& n) { return n; }

Now that we have that in place, what about the containers? This is the harder part, that warrants the title of this post. One approach would be to have the target container passed by reference and then filled from the source container. This is really trivial:

template <typename In, typename Out>
void convert3(const In& inCont, Out& outCont)
{
    for (In::const_iterator it = inCont.begin(); it != inCont.end(); ++it)
        outCont.push_back(scalar_convert(*it));
}

This leaves to the original scalar_convert<T> all the trouble of specifying what the element type of the target container should be.

What’s much less trivial is the original requirement that you return an instance of the new container filled with the converted elements. After all, how can you create a new instance of a container with a different element type if you don’t know in advance what container it’s going to be?

Enter template template parameters, which are covered in more detail here. Basically, a template template parameter allows you to specify that a template parameter is in fact a template in itself, and has template parameters that you can, in turn, specify.

In our case:

template <typename In, template <typename _X,
                                
typename _Alloc = std::allocator<_X>>
                       class Cont
>
Cont<typename convert_traits<In>::to_type> vector_convert(
                                               const Cont<In>& cont)
{
    Cont<typename convert_traits<In>::to_type> converted;
    for (Cont<In>::const_iterator it = cont.begin(); it != cont.end(); ++it)
        converted.push_back(scalar_convert(*it));
    return converted;
}

Whoa.

This looks bad, but if you dissect this function to its constituents it will all make sense. It’s a template function, and its first template parameter is the element type of the source container. The container type itself is called Cont, but it’s not a real type—it can be std::vector or std::list but not std::vector<int> or std::list<double>—it’s just the name of the template class without the template parameter. This Cont type has template parameters of its own: _X which is the element type and _Alloc which is the allocator, conveniently defaulting to the default STL allocator here.

This enables us to declare a new instance of this container, parameterized with the target type from the convert_traits structure, and then push the converted elements into it. (Obviously the previous approach where the output container is passed by reference has its advantages, e.g. it’s probably more efficient and enables multiple conversions into the same container.)

Parallelism in Visual Studio 2010: Demos Updated to Beta 2

As you probably know, Visual Studio 2010 has reached the Beta 2 milestone, with a go-live license available to start coding your production applications using this release.

There have been some minor changes around the System.Threading.Tasks namespace and classes, with the most significant change being around the cancellation model for tasks. Instead of explicitly reaching out for a Task object and then calling its Cancel method (which has been removed, along with the static Task.Current property), cancellation now requires a CancellationTokenSource object to be created, its Token property should be passed to the methods that create a task, and then its Cancel method can be used to cancel the task hierarchy using that cancellation token.

There’s more information about these changes on the Parallel FX team blog.

A few weeks ago I posted slides and code for parallelism demos in Visual Studio 2010. I now updated these demos to work on Beta 2, and you can download them as usual. (The only changes have been around the new cancellation model and the removal of the ConcurrentLinkedList<T> collection.)

Configuring Automatic Crash Dumps

This post is meant to serve as a simple reference for configuring automatic crash dumps for managed and native applications. These configuration steps can be performed on any machine which has Debugging Tools for Windows installed, and they do not require Visual Studio.

Although the subsequent steps are configured to capture a crash dump and nothing more, cdb is a fairly sophisticated debugger and so you can perform much more than just capture a dump—you can pass any commands of your choice to the debugger and they will be executed when the application crashes. (E.g. run an external program that sends an email, capture some data into a log file, etc.—consult the Debugging Tools for Windows documentation for information about the debugger commands.)

Native Applications

Go to the HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug registry key and insert the following values:

Debugger = "C:\Program Files\Debugging Tools for Windows\cdb.exe" -pv -p %ld -c ".dump /u /ma C:\Temp\CrashDumps\crash.dmp;qd"
Auto = "1"

As a result, whenever a native process crashes, cdb will automatically attach to it, grab a dump to the specified directory and detach the debugger, allowing the standard Windows Error Reporting mechanism to kick in.

[Prior to Vista, you could also retain the default crash dump collection settings for native applications by running drwtsn32 -i from the command line and configuring Dr. Watson to capture a full dump by running drwtsn32 without command line parameters.]

Managed Applications

Go to the HKLM\SOFTWARE\Microsoft\.NETFramework registry key and insert the following values:

DbgManagedDebugger = "C:\Program Files\Debugging Tools for Windows\cdb.exe" -pv -p %ld -c ".dump /u /ma C:\Temp\CrashDumps\crash.dmp;qd"
DbgJITDebugLaunchSetting = 2

As a result, whenever a managed process crashes, cdb will automatically attach to it, grab a dump to the specified directory and detach the debugger, allowing the standard Windows Error Reporting mechanism to kick in.

64-bit Systems

On 64-bit systems, replicate the same registry settings to the appropriate Wow6432Node key, i.e. modify the registry key prefix in the above instructions to HKLM\SOFTWARE\Wow6432Node\Microsoft instead of HKLM\SOFTWARE\Microsoft. If you don’t do this, the settings will be relevant only for 64-bit applications. Note that you should use the appropriate version of the debugger—for the 64-bit key, specify the path to the 64-bit cdb and for the 32-bit key, specify the path to the 32-bit cdb.

WER Local Dumps

On Vista SP1 / Server 2008 and newer OS releases, you can configure Windows Error Reporting to record a dump of your application to a folder of your choice as part of the standard error reporting sequence when a process crashes. To do so, go to the HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps registry key and insert the following values:

DumpFolder = "%LOCALAPPDATA%\CrashDumps"
DumpCount = 100
DumpType = 2

What I Learned About Writing Unit Tests: Dependency Injection Mess With Mocks

Armed with some experience, I embraced dependency injection in all its might. I started writing subsystems and components that interact only through well-defined interfaces, which was relatively easy for me because my previous infrastructure project relied heavily on dynamically-generated proxies that worked only with interfaces. This allowed me to abstract away and stub away everything a component needed under a test.

And then my tests had the following shape and form (I’m not using any specific mock framework syntax, for illustration purposes):

[TestMethod]
public void LoggingFramework_LogToDB_Works()
{
    bool flushed = false;

    SomeMock<ILogDatabaseProvider> provider =
        SomeMockProduct.Mock<ILogDatabaseProvider>();
    provider.Expect(m => m.WriteLog).DoNothing().Once();
    provider.Expect(m => m.ReadLog).Return(new string[] { “MyMessage” });

    SomeMock<IConsoleOutput> console =
        SomeMockProduct.Mock<IConsoleOutput>();
    console.Expect(c => WriteLine).DoNothing().Once();
    console.Expect(c => c.Flush).Callback(() => flushed = true).Once();

    //…repeat for another dozen components…

    Log log = new Log(provider, console, …);
    log.Write(“MyMessage”, Severity.Critical);

    provider.Verify();
    console.Verify();
    //…all other providers—Verify()

    Assert.IsTrue(flushed, “Log console was not flushed”);
}

In the beginning, I was very impressed with the flexibility of this approach. I can over-specify the hell out of my tests, and define the subtlest behaviors for each of the methods called under test without writing a manual implementation of the mocked component tailored for each and every test.

This went very well for a couple of months, and I had no trouble at all adding more and more code and more and more tests (until I had around 50KLOC of code and 75KLOC of tests). But then, some changes in the design goals warranted a change in the system’s interfaces, and not only have the names and parameters changed, but so have the semantics. (For example, it became not OK to flush a log without messages written into it; it became not OK to write to a console unless the log was explicitly created with a console; and so on.)

I was horrified by the number of changes I had to make to my tests. Even in areas when I encapsulated some of the mocking logic to a separate function, I had to rewrite more test code lines—by an order of magnitude—than the number of lines I changed in the actual code.

Apparently, this is a well-known phenomenon of overly-specified and thus very brittle tests. I had to learn it the hard way. In the next installment, I should hopefully wrap up this series by explaining the more pragmatic approach I now use when writing unit tests.

Analyzing Monitor-Based Deadlocks with SOS.dll

Over a year ago, I blogged about the SOSEX debugging extension (which has been updated since!) and how its !dlk command can be used to diagnose a managed deadlock that involves Monitor locks.

There’s also the obvious question of what to do when SOSEX can’t be used for this purpose, i.e. how to diagnose this kind of deadlock with SOS alone.

First of all, you need to see the sync blocks involved. The SOS !syncblk command (and the !dumpheap -thinlock command) will show you information about the sync blocks in the debugged process or dump. (Sync blocks are the CLR mechanism behind the lock statement and the Monitor class.)

0:000> !syncblk
Index         SyncBlock MonitorHeld Recursion Owning Thread Info          SyncBlock Owner
    1 0000000002551e88            3         1 00000000025509a0   720   3   0000000002983cd8 ADeadlockOfSorts.BankAccount
    2 0000000002551ed0            3         1 000000000251e580  1608   0   0000000002983cc0 ADeadlockOfSorts.BankAccount
-----------------------------
Total           2
CCW             0
RCW             0
ComClassFactory 0
Free            0

What you see in this output is two sync blocks, both belonging to objects of type BankAccount (this is the object instance that was passed to the lock statement or the Monitor.Enter method). You can also see the owning thread information (Windows thread ID and debugger thread number) for each of the sync blocks.

Now we need to know what each of the application threads are waiting for. We know about the locks they hold, but we don’t know about the locks they are trying to acquire. First, let’s take a look at all the managed threads using the !threads command:

0:000> !threads
ThreadCount: 3
UnstartedThread: 0
BackgroundThread: 2
PendingThread: 0
DeadThread: 0
Hosted Runtime: no
                                              PreEmptive                                                Lock
       ID OSID        ThreadOBJ     State   GC     GC Alloc Context                  Domain           Count APT Exception
   0    1 1608 000000000251e580   200a020 Enabled  0000000002983df0:0000000002983fd0 0000000000382df0     1 MTA
   2    2 159c 0000000002521d90      b220 Enabled  0000000000000000:0000000000000000 0000000000382df0     0 MTA (Finalizer)
   3    3  720 00000000025509a0   380b220 Enabled  0000000002984090:0000000002985fd0 0000000000382df0     1 MTA (Threadpool Worker)

So we have three threads here capable of executing managed code—the main application thread (ID 0), the finalizer (ID 2) and a thread-pool thread (ID 3). What are they up to?

0:000> ~*e !CLRStack
OS Thread Id: 0x1608 (0)
Child-SP         RetAddr          Call Site
000000000027e7f0 000007fee146d502 ADeadlockOfSorts.Program.Main(System.String[])
OS Thread Id: 0x159c (2)
Failed to start stack walk: 80004005
OS Thread Id: 0x720 (3)
Child-SP         RetAddr          Call Site
000000001b21f4b0 000007fee0142bbb ADeadlockOfSorts.Program+<>c__DisplayClass3.<Main>b__2(System.Object)
000000001b21f510 000007fee01b7411 System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
000000001b21f560 000007fee01b724f System.Threading._ThreadPoolWaitCallback.PerformWaitCallbackInternal(System.Threading._ThreadPoolWaitCallback)
000000001b21f5b0 000007fee146d502 System.Threading._ThreadPoolWaitCallback.PerformWaitCallback(System.Object)

So we have three threads in the output, but the finalizer is not executing any code. However, it’s not obvious from what we see here what threads 0 and 3 are doing. (On a 32-bit machine, BTW, the stack would explicitly contain Monitor.Enter.)

Therefore, we have to resort to a native stack dump using the kb command:

0:000> ~*kb

.  0  Id: 1504.1608 Suspend: 1 Teb: 000007ff`fffde000 Unfrozen
RetAddr           : Args to Child                                                           : Call Site
000007fe`fdad2fa2 : 00000000`00344b30 00000000`00000010 000000d0`006a000a 00000000`003487d0 : ntdll!NtWaitForMultipleObjects+0xa
00000000`77782363 : 00000000`0027e1a8 00000000`0027e1a0 00000000`00000000 00000000`00000208 : KERNELBASE!WaitForMultipleObjectsEx+0xe8
000007fe`e12a65f9 : 00000000`ffffffff 00000000`00000000 00000000`0251e580 00000000`00000001 : KERNEL32!WaitForMultipleObjectsExImplementation+0xb3
000007fe`e12abac5 : ffffffff`00000001 00000000`02551ea0 00000000`0251e580 000007fe`e12be1b4 : mscorwks!WaitForMultipleObjectsEx_SO_TOLERANT+0xc1
000007fe`e12ebe9d : 00000000`00000000 00000000`02551ea0 00000000`00000000 00000000`ffffffff : mscorwks!Thread::DoAppropriateAptStateWait+0x41
000007fe`e12c75c0 : 00000000`0027e810 000007fe`e187b2e8 00000000`02551ea0 00000000`00000000 : mscorwks!Thread::DoAppropriateWaitWorker+0x191
000007fe`e1399afa : ffffffff`fffffffe 00000000`00000001 00000000`00000fc8 00000000`00000000 : mscorwks!Thread::DoAppropriateWait+0x5c
000007fe`e13dc2b1 : 00000000`02551e88 00000000`0027e810 00000000`0251e580 00000000`0251e580 : mscorwks!CLREvent::WaitEx+0xbe
000007fe`e127c006 : 00000000`02551e88 00000000`0027e810 00000000`ffffffff 00000000`00000000 : mscorwks!AwareLock::EnterEpilog+0xc9
000007fe`e180a9c5 : 00000000`00000001 000007fe`e189f200 00000000`0251e580 00000000`0251e580 : mscorwks!AwareLock::Enter+0x72
000007ff`001802d0 : 00000000`000003e8 00000000`00000000 00000000`02983cbc 00000000`0027e7d0 : mscorwks!JIT_MonEnterWorker_Portable+0xf5
000007fe`e146d502 : 00000000`02983bf8 000007fe`e134240a 000007fe`e1215890 00000000`00000000 : 0x7ff`001802d0
000007fe`e1329fd3 : 00000000`00000000 000007fe`e027ec90 00000000`00000000 00000000`00000000 : mscorwks!CallDescrWorker+0x82
000007fe`e133a3af : 00000000`0027ea38 00000000`00000008 00000000`0027ec50 00000000`0027ea38 : mscorwks!CallDescrWorkerWithHandler+0xd3
000007fe`e12adc7f : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`0027eeb0 : mscorwks!MethodDesc::CallDescr+0x24f
000007fe`e1291c74 : 00000000`00000000 00000000`00000000 00000004`0016003a 00000000`00000000 : mscorwks!ClassLoader::RunMain+0x22b
000007fe`e12c9955 : 00000000`0027f4a0 00000000`00000000 00000000`02523068 00000000`00000200 : mscorwks!Assembly::ExecuteMainMethod+0xbc
000007fe`e13ddb07 : 00000000`0036a860 000007fe`fb5e0000 00000000`00000000 000007fe`e1407762 : mscorwks!SystemDomain::ExecuteMainMethod+0x491
000007fe`e129855c : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`0036a860 : mscorwks!ExecuteEXE+0x47
000007fe`fb5f015e : ffffffff`ffffffff 00000000`0251e580 000007fe`fb5f2fd0 000007fe`fb763a18 : mscorwks!CorExeMain+0xac

…snipped the finalizer thread for brevity…

   3  Id: 1504.720 Suspend: 1 Teb: 000007ff`fffd7000 Unfrozen
RetAddr           : Args to Child                                                           : Call Site
000007fe`fdad2fa2 : 00000000`025509a0 00000000`00000000 ffffffff`fffffffe 00000000`00000000 : ntdll!NtWaitForMultipleObjects+0xa
00000000`77782363 : 00000000`1b21ee68 00000000`1b21ee60 00000000`00000000 000007fe`e11fcbe0 : KERNELBASE!WaitForMultipleObjectsEx+0xe8
000007fe`e12a65f9 : 00000000`ffffffff 00000000`00000000 00000000`025509a0 00000000`00000001 : KERNEL32!WaitForMultipleObjectsExImplementation+0xb3
000007fe`e12abac5 : ffffffff`00000001 00000000`02551ee8 00000000`025509a0 000007fe`e12be1b4 : mscorwks!WaitForMultipleObjectsEx_SO_TOLERANT+0xc1
000007fe`e12ebe9d : 00000000`00000000 00000000`02551ee8 00000000`00000000 00000000`ffffffff : mscorwks!Thread::DoAppropriateAptStateWait+0x41
000007fe`e12c75c0 : 00000000`00000000 00000000`00000000 00000000`02551ee8 00000000`00000000 : mscorwks!Thread::DoAppropriateWaitWorker+0x191
000007fe`e1399afa : ffffffff`fffffffe 00000000`00000001 00000000`025509a0 00000000`00000000 : mscorwks!Thread::DoAppropriateWait+0x5c
000007fe`e13dc2b1 : 00000000`02551ed0 00000000`1b21f4d0 00000000`025509a0 00000000`025509a0 : mscorwks!CLREvent::WaitEx+0xbe
000007fe`e127c006 : 00000000`02551ed0 00000000`1b21f4d0 00000000`ffffffff 00000000`00000000 : mscorwks!AwareLock::EnterEpilog+0xc9
000007fe`e180a9c5 : 00000000`00000001 000007fe`e189f200 00000000`025509a0 00000000`025509a0 : mscorwks!AwareLock::Enter+0x72
000007ff`00180535 : 00000000`000003e8 00000000`00000000 00000000`02983fe8 00000000`00000000 : mscorwks!JIT_MonEnterWorker_Portable+0xf5
000007fe`e0142bbb : 00000000`02983ca0 00000000`00000000 00000000`1b21f3f0 00000000`00000000 : 0x7ff`00180535
000007fe`e01b7411 : 00000000`1b21f3e8 00000000`064c784b 00000000`02983d30 00000000`128d1030 : mscorlib_ni+0x2f2bbb
000007fe`e01b724f : 00000000`00000000 00000000`00000000 00000000`02983dd4 00000000`02528020 : mscorlib_ni+0x367411
000007fe`e146d502 : 00000000`00000000 000007fe`e1902760 ffffffff`fffffffe 000007fe`e187b2e8 : mscorlib_ni+0x36724f
000007fe`e1329fd3 : 00000000`00000173 000007fe`e02c3698 00000000`00383148 00000000`00000000 : mscorwks!CallDescrWorker+0x82
000007fe`e1321c3a : 00000000`1b21f870 000007fe`e133d901 ffffffff`fffffffe 00000000`00000001 : mscorwks!CallDescrWorkerWithHandler+0xd3
000007fe`e12dd0bf : 000007fe`dfed7ac8 000007fe`dfe51000 000007fe`e1a8f568 000007fe`e13154ec : mscorwks!DispatchCallDebuggerWrapper+0x3e
000007fe`e13e2f17 : 00000000`1b21f9e0 00000000`025509a0 00000000`025509a0 00000000`025509a0 : mscorwks!DispatchCallNoEH+0x5f
000007fe`e12ac1a0 : 00000000`00000002 00000000`00000000 00000000`00000000 000007fe`e132d1de : mscorwks!QueueUserWorkItemManagedCallback+0x83

This call stack explicitly reveals that both threads are waiting on a lock; we can see the parameters to mscorwks!AwareLock::Enter, and the third parameter on each call stack is the sync block itself that the thread is trying to lock. Note that we don’t see the object instance here, but we certainly do see the sync block—and correlating it with the !syncblk output above is enough to reach a conclusion.

What we have here is thread 0 waiting for sync block 0000000002551e88 which is held by thread 3 which waits for sync block 0000000002551ed0 which is held by thread 0. We have a wait chain with a cycle in it, and therefore a deadlock.

Nitpicker’s corner: Even if we didn’t see the sync block parameter on the stack, we could use .frame /r 9 to see the register values on the AwareLock::Enter frame and deduce the sync block address from the ECX register:

0:000> .frame /r 9
09 00000000`0027e5f0 000007fe`e180a9c5 mscorwks!AwareLock::Enter+0x72
rax=000000000251e580 rbx=0000000002551e88 rcx=000000000251e580
rdx=0000000000000001 rsi=000000000027e6b8 rdi=000000000251e580
rip=000007fee127c006 rsp=000000000027e5f0 rbp=000000000027e810
r8=0000000002551ea0  r9=0000000000000000 r10=0000000000000000
r11=0000000000000202 r12=0000000000000000 r13=0000000000000000
r14=0000000000000000 r15=000007fee146bc60
iopl=0         nv up ei pl zr na po nc
cs=0033  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000244
mscorwks!AwareLock::Enter+0x72:
000007fe`e127c006 ebc6            jmp     mscorwks!AwareLock::Enter+0x3a (000007fe`e127bfce)

But if you have a call stack with valid parameters, it’s much better.

What I Learned About Writing Unit Tests: Test Infrastructure

In the previous installment I mentioned that I wasn’t satisfied with tests that check whether a single constructor throws a single exception. Over the years I started looking for something with a little more value, a test that I could show developers writing code for my framework and tell them that’s the way to use my APIs.

Naturally, the next thing I started doing was writing infrastructure frameworks for writing tests for my framework. This means I would have all kinds of TestHelper and ContextHelper and TestSetupReflector classes that would take care of everything necessary to make the test short and to the point. My tests from that period would be something along the following lines:

[TestMethod]
public void LoggingFramework_LogToDB_Works()
{
    using (LogTestHelper logH = new LogTestHelper())
    using (DataHelper daH = new DataHelper(logH.ConnectionString))
    {
        Log log = new Log(logH.Name);
        log.Write(“MyMessage”, Severity.Critical);
        daH.Flush().VerifyMessage(“MyMessage”, Severity.Critical);
    }
}

This was all very elegant and gave me the power to write a new test with a fairly sophisticated framework that shows a realistic scenario of how the Log class would be used in a production environment.

Unfortunately, this infrastructure nonsense has nothing in common with the way my users are going to work with the API. The infrastructure obstructs the actual work done in the test, and is so brittle that even a minor change to the framework warrants an extensive rewrite of the test infrastructure. (At least the infrastructure changes would be constrained to a single location—after all, the test infrastructure is a good demonstration of SCP.)

Besides, that was all fun and games while I still could easily create a testing environment for relatively simple frameworks. When I needed a test infrastructure for bringing up multiple components and hooking up the relationships between them, I started seriously thinking about dependency injection.

What I Learned About Writing Unit Tests: My First Tests

Over the last 4 years, I embraced the idea of writing unit tests for my software. Most of what I’ve written during these years has been software frameworks, with very high reliability and stability guarantees and explicit needs for backwards compatibility—all perfectly ripe for a good unit test suite. In the following short series of posts, I will try to share the story of what I learned from writing unit tests, and why the tests I write today are nothing like the tests I wrote 4 years ago.

The first unit tests I’ve written were taken straight from “the book”. I would take a class, strip it of all its dependencies and test every method and every constructor and every possible feature of it. These tests would be somewhat similar to the following:

[TestMethod]
[ExpectedException(typeof(ArgumentNullException))]
public void LoggingFramework_LogCtorWithNullString_Throws()
{
    new Log(null);
}

I got very high code coverage with this kind of tests, but I couldn’t stop thinking that they didn’t bring much value to my software. I mean, yes, it’s important that the Log constructor throws a specific exception when passed a null string, and it’s even more important because it’s written in the public API documentation that I ship with the framework. But writing hundreds of such tests by hand and then saying that I have 100% code coverage didn’t convince me that my framework worked properly.

Specifically, even though it might belong to the QA department, when designing a framework it’s critical to test the APIs of that framework in a realistic way. It must be possible to design a unit test (not a system test, not an integration test) that tests the API and not just a single constructor at a time.

Learning from Feedback as a Public Speaker

Over the last three years, I’ve had lots of experiences as a speaker at conferences, courses, private presentations and other opportunities. Among them, I had the chance to present at the Microsoft Developers Academy, TechEd and IDCC; I taught 54 courses for Sela, including Windows Internals, .NET Debugging, .NET Performance, C++/CLI and many others; and I lectured at short half-day MSDN events on Windows 7, Windows Server 2008, performance, debugging and concurrency.

Almost every training session, every course, every conference concluded with audience feedback. (If you ever filled an evaluation form for my presentation or course, thank you for your time and feedback!) I’ve been meticulously collecting this feedback for the past three years, and figured that now would be a good time to look back and share with you how you think I’ve been doing, and what I’ve been doing with this information.

They say that positive feedback is all very similar; negative feedback is varied and interesting. Here are some of the things I’ve noticed during the past three years.

“Less Code, More Theory”

This is something I’ve been hearing for a long time during the first couple of years, and always wanted to work on. I guess from a certain perspective it’s just that much easier for me to focus on what I’m really good at—showing deep technical demos, writing lots of code on the stage, typing commands into the debugger, and so on. It was much harder for me to talk when I didn’t have any code or live demo to back me up.

During the last year, I focused more and more on subjects such as design for concurrency, performance testing methodology and case studies, architecture of distributed system and other topics that often can’t be accompanied by a simple code demo and must be explained using hand-waving. This is certainly not my comfort zone but I’m pretty happy with the results so far, and will keep trying to get better at it.

“Way Over My Head”

Almost every one of my conference presentations, courses, half-day sessions has been tagged level-400. Often enough it was even more hardcore than many other level-400 sessions at the same conference. So it shouldn’t be a big surprise to my audience that my lectures often require deep technical knowledge, lots of practical experience and the ability to focus on small details as well as the big pictures for a couple of hours straight (which I know is not easy—I always find it exceptionally difficult to keep myself focused on the speaker when sitting in the audience at a conference).

Nonetheless, often enough I get feedback indicating that I was talking too fast, or going over too many details, or diving deep into a piece of technology and assuming it’s just familiar to everyone. This is something I do way too often. Over time I managed to create a certain distance from the subject matter of my lectures, and through this distance I understand how the audience is absorbing my presentation. Still, predicting how easy or hard it’s going to be for other people to take in a particular piece of information is something I need to work on. And after all, everyone would be much better off if I simply cut the material in half but presented it thoroughly and slowly rather than lose half of the audience half-way through the session.

“Introduction Too Long”, or “There Wasn’t Enough Time to Talk about X”

This is a piece of feedback I’ve been getting recently, and I suspect it has something to do with the way I’m handling “Less Code, More Theory”. As I gain familiarity with a subject and observe it from different angles, there’s obviously more for me to rant about in the introductory part of my sessions. For example, when speaking about concurrency and parallelism I can often find myself thirty minutes in without even mentioning a specific technology yet—I can just go on and on talking about how parallelism is vital to modern applications.

On the other hand, if I make the introductions too short I’m pretty sure we’ll be getting back to “Way Over My Head” and “Less Code, More Theory”. I’ll have to see how I can incorporate this piece of feedback into my shorter presentations, where there’s little time to spend on a stretched introduction.

“More Code / Demos, Less Slides”

I never believed I’d see this feedback on a session of mine, but apparently my efforts to get out of the live coding comfort zone might have gone a little over the edge for some folks. I know for certain that seeing 30 slides in the row is the most boring thing known to mankind, and I profoundly apologize if my storytelling skills are not up to par with the boredom-inflicting nature of a demo-less presentation. However, I also feel that sometimes not focusing on a particular technology and not driving the point home with a demo is more beneficial if there’s a general-purpose message to deliver.

I can’t promise you that my future presentations are going to have more slides or more pictures, less code or less live demos—but I can tell you this: I greatly appreciate your feedback over these years, and I’m striving to improve with every bit of it.