Fix nested spin locks in thread pool etw firing (#17677)
authorKoundinya Veluri <kouvel@users.noreply.github.com>
Fri, 20 Apr 2018 02:47:52 +0000 (19:47 -0700)
committerGitHub <noreply@github.com>
Fri, 20 Apr 2018 02:47:52 +0000 (19:47 -0700)
`UnManagedPerAppDomainTPCount::QueueUnmanagedWorkRequest` fires an ETW event inside a spin lock and a nested spin lock is taken here:

```
SpinLock::GetLock + 0x8E (0x719da71d)
EventPipeBufferManager::AllocateBufferForThread + 0x7B (0x71afa92e)
EventPipeBufferManager::WriteEvent + 0x250 (0x71afbe0a)
EventPipe::WriteEventInternal + 0x125 (0x71951c93)
EventPipe::WriteEvent + 0x91 (0x71951714)
EventPipeWriteEventThreadPoolEnqueue + 0x9E (0x71d468a6)
FireEtwThreadPoolEnqueue + 0xF (0x71b7a04b)
UnManagedPerAppDomainTPCount::QueueUnmanagedWorkRequest + 0x21D (0x71b7a597)
```

Nesting spin locks is not allowed, moved the ETW firing outside the lock.

src/vm/threadpoolrequest.cpp

index 523a063..66fe1f4 100644 (file)
@@ -420,14 +420,15 @@ void UnManagedPerAppDomainTPCount::QueueUnmanagedWorkRequest(LPTHREAD_START_ROUT
     _ASSERTE(pWorkRequest != NULL);
     PREFIX_ASSUME(pWorkRequest != NULL);
 
+    if (ETW_EVENT_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, ThreadPoolEnqueue) && 
+        !ThreadpoolMgr::AreEtwQueueEventsSpeciallyHandled(function))
+        FireEtwThreadPoolEnqueue(pWorkRequest, GetClrInstanceId());
+
     m_lock.Init(LOCK_TYPE_DEFAULT);
     
     {
         SpinLock::Holder slh(&m_lock);
 
-        if (ETW_EVENT_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, ThreadPoolEnqueue) && 
-            !ThreadpoolMgr::AreEtwQueueEventsSpeciallyHandled(function))
-            FireEtwThreadPoolEnqueue(pWorkRequest, GetClrInstanceId());
         ThreadpoolMgr::EnqueueWorkRequest(pWorkRequest);
         pWorkRequest.SuppressRelease();
         m_NumRequests++;