Many young or new developers have sometimes hard to deal mind set. Imagine you are developing big product and you about to release it. And then QA found problem that must be fixed. Fix is small and it looks like it is affecting only really small area that can be easily tested. And there is temptation to fix it, test only that small area by R&D and release it. And I will show that there is no such thing as safe change.

But before I will go to example from my experience, I have to remind you, that any application has a lot of bugs. Even “hello world” application can have some bugs especially if it does use run-time library.

Imagine you have some field myIntf of type IMyInterface in some class and that interface is implemented in native code. In some cases, it is useful to know which thread was used to introduce this interface to .NET first time. It is useful, because this interface would be connected/attached to that thread and call of any function from that interface will attempt to marshal execution to that thread, unless it is free threaded. And this thread could be blocked, destroyed etc.

So, imagine you have following code:
myIntf.Func1();

If you add Debug.Break(); before this line code and run your application from WinDbg and wait until execution will stop. Next, press

These days many Intel based laptops have two video cards: one that built-in in CPU and much better one. This happens because Intel is not capable to making nice GPU and as result these notebooks works just fine in Windows, but their performance is quite bad for most of the games.  Unless of couse you are willing to sacrifice everything in graphics quality. And as result of that manufacturers add secondary, much better GPU, so their customers can play games. AMD has much better GPU in their APU and usually they don’t have second GPU.

And I was asked to check why Minecraft is quite slow on such Intel based laptop. Firstly, I would like to check if Minecraft in

I was asked to investigate why our application sometimes forcefully terminated by Windows. After first few minutes I did realize that Windows terminated application with STATUS_HEAP_CORRUPTION. After that I asked our QA to follow https://docs.microsoft.com/en-us/windows/win32/wer/collecting-user-mode-dumps and change DumpType to 2 to collect full crash dumps. Unfortunately, after checking few of these reports, I found that application crashing in pretty much random places: WPF rendering, DirectX engine or sometimes even in network stack. It is clear, that corruption happens some time ago and no useful information. I need different approach.

Windows has built-in feature that will allow to find few common problems. To enable these features, you need to install Windows Debugging Tools from Windows SDK and run gflags. Here

Disclaimer. This is perhaps not a best way to do, but I couldn’t find any better way.

Let’s imagine that you have some Task to run in the background. And that task has to update UI for example progress bar. Or that task has to call some callbacks in context of main thread. For firs case you would use Invoke, for second case you would use SynchronizationContext.Send. Implementation is very simple. WinForms will add request to queue of requests and post message to main thread and then it wait on request handle to be signaled. Main thread receives message, processes request and signal on request event. Very simple and quite basic. Post is the same as Send but

In this post I will explain my investigation about handle leaks and how it resulted in interesting discovery in MemoryCache class.

I received few reports stating that our application consuming handles even when it supposed to do nothing. And then I started my investigation. I explained how to find where is leaking handles here.

After application leaked about 50 handles, I paused application and checked call stack. And to my surprise I found a lot of callstack that looks like this:

ntdll!NtCreateThreadEx+0x0000000000000014
KERNELBASE!CreateRemoteThreadEx+0x0000000000000294
KERNELBASE!CreateThread+0x000000000000003b
verifier!AVrfpCreateThread+0x00000000000000bf
clr!Thread::CreateNewOSThread+0x00000000000000b2
clr!Thread::CreateNewThread+0x0000000000000091
clr!ThreadpoolMgr::CreateUnimpersonatedThread+0x00000000000000cb
clr!ThreadpoolMgr::MaybeAddWorkingWorker+0x000000000000011c
clr!ManagedPerAppDomainTPCount::SetAppDomainRequestsActive+0x0000000000000024
clr!ThreadpoolMgr::SetAppDomainRequestsActive+0x000000000000003f
clr!ThreadPoolNative::RequestWorkerThread+0x000000000000002b
--------------------------------------
ntdll!NtCreateEvent+0x0000000000000014
verifier!AVrfpNtCreateEvent+0x0000000000000080
KERNELBASE!CreateEventW+0x000000000000006b
verifier!AVrfpCreateEventW+0x00000000000000a5
clr!CLREventBase::CreateManualEvent+0x000000000000003a
clr!Thread::AllocHandles+0x000000000000007b
clr!Thread::CreateNewOSThread+0x000000000000007f
clr!Thread::CreateNewThread+0x0000000000000091
clr!ThreadpoolMgr::CreateUnimpersonatedThread+0x00000000000000cb
clr!ThreadpoolMgr::MaybeAddWorkingWorker+0x000000000000011c
clr!ManagedPerAppDomainTPCount::SetAppDomainRequestsActive+0x0000000000000024
clr!ThreadpoolMgr::SetAppDomainRequestsActive+0x000000000000003f
clr!ThreadPoolNative::RequestWorkerThread+0x000000000000002b
mscorlib_ni!DomainNeutralILStubClass.IL_STUB_PInvoke()$##6000000+0x0000000000000069

From this callstack it wasn’t really obvious what part of

I received few reports stating that our application consuming handles even when it supposed to do nothing. And then I started my investigation. At the beginning I would like to find if it is possible to find handle leaks with some tools. And I immediately found video by Jeff Dailey I believe: https://channel9.msdn.com/Blogs/jeff_dailey/Understanding-handle-leaks-and-how-to-use-htrace-to-find-them who explained how to do it. This video is more than 13 years old. I will explain steps here, because I really hate videos. It is much faster to read than watch.

You need to run C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\gflags.exe and it is usually installed with Debugging Tools and part of Windows SDK. You will see something like this:

Imagine situation that .NET attempts to release last reference to COM object but due to mismanage on native side, object already destroyed. In our application when native object is destroyed, we fill object with hexadecimal 80. In this case any attempt to release will immediately crash and you will see something like this:

00 000000c6`b97fa430 00007ffa`a13283bd : 00000000`00000000 000001df`76eee2d0 000001df`453f6fd0 00007ffa`a11aee14 : clr!SafeReleasePreemp+0x75
01 000000c6`b97fa4a0 00007ffa`a1328296 : 00000000`05213028 000001df`453f6fd0 000001df`4543af68 00000000`00000000 : clr!RCW::ReleaseAllInterfaces+0xed
02 000000c6`b97fa4f0 00007ffa`a13281ab : 00000000`05213028 000001df`453f6fd0 000000c6`b97fa5c0 00007ffa`41dd4e90 : clr!RCW::ReleaseAllInterfacesCallBack+0x53
03 000000c6`b97fa580 00007ffa`a1391c5e : 000001df`7a47d7b0 000000c6`babffaa8 00007ffa`41cecfa8 00007ffa`d7571a9a : clr!RCW::Cleanup+0x64

Second parameter in SafeReleasePreemp is RCW and you can use !DumpRCW and you will see something like that:

!DumpRCW 000001df`76eee2d0

If you work with COM objects you may accidently attempt to use or create COM object in one thread and accidently use it in another thread. And then unless original thread is free threaded .NET will attempt to switch to original thread.

And from there you will see one of the following outcomes.

  1. If that thread pump messages, then .NET will attempt to send message to that thread to switch. Sometimes it can lead to deadlock or just long delay if that thread is busy. Main thread usually pumps messages, so usually .NET able to switch to main thread.
  2. You will get error that Interface is not supported. Sometimes you will get that cryptic message even that interface is clearly supported. You will get this message because .NET don’t know how to marshal to original thread, specially if this is some background thread. In this case .NET is not able to marshal, so it will ask object itself to marshal by requesting few interfaces and one of them is IMarshal. Most objects do not support these interfaces and you will see that error message
  3. When original thread was terminated, or if that was thread pool thread and it will clean its state on next request. In this case you will get this one from MDA: Managed Debugging Assistant 'DisconnectedContext' : 'Transition into COM context 0xed058 for this RuntimeCallableWrapper failed with the following error: The object invoked has disconnected from its clients. (Exception from HRESULT: 0x80010108 (RPC_E_DISCONNECTED)). This is typically because the COM context 0xed058 where this RuntimeCallableWrapper was created has been disconnected or it is busy doing something else. Releasing the interfaces from the current COM context (COM context 0xec968). This may cause corruption or data loss. To avoid this problem, please ensure that all COM contexts/apartments/threads stay alive and are available for context transition, until the application is completely done with the RuntimeCallableWrappers that represents COM components that live inside them.'