The debugger may stop responding when mixed-mode debugging a debuggee that uses more than 63 thread local storage slots

Article translations Article translations
Article ID: 939969 - View products that this article applies to.
Expand all | Collapse all

SYMPTOMS

Consider the following scenario. An application is running under a mixed mode debugger, also known as an "interop-debugger." The debuggee has not loaded the common language runtime (CLR). The debuggee allocates more than 63 thread local storage (TLS) slots, and then the debuggee loads the CLR. In this scenario, the debugger stops responding, and the debugger may consume 100 percent of the CPU usage. If the debuggee is stopped by using Task Manager, the debugger becomes responsive again.

Note This problem may also occur with any mixed-mode debugger that uses the ICorDebug interfaces (specifically Microsoft Visual Studio .NET 2002, Visual Studio .NET 2003, and Visual Studio 2005) for those corresponding runtimes.

CAUSE

This problem occurs because the CLR uses TLS slots. The mixed-mode debugger must read the CLR’s TLS slots from out of process, and the mixed-mode debugger does not correctly read slots that have an index above 63.

WORKAROUND

To work around this problem, use one of the following methods:
  • Use the managed-only debugger or the native-only debugger instead of the mixed-mode debugger.
  • Modify the debuggee to load the CLR early. TLS slots are allocated based on a first-come, first-served basis. Therefore, if the debuggee loads the CLR early, fewer slots will be allocated.
  • Modify the debuggee to reserve fewer TLS slots for the CLR. You can allocate several slots, and then free these slots before the CLR is loaded. To do this, use the following sample code.
    #include "stdafx.h"
    #include "windows.h"
    
    const int NumSlots = 20; 
    DWORD g_slots[NumSlots];
    
    // Call this from Main
    // This "reserves" the low TLS slots for the CLR.
    void AllocateSlots()
    {
        for(int i = 0; i < NumSlots; i++)
        {
            g_slots[i] = TlsAlloc();
        }
    }
    
    // Call this after your application finishes allocating its own TLS slots, but 
    // before you load any managed code.
    void FreeSlots()
    {
        for(int i =0; i < NumSlots; i++)
        {
            TlsFree(g_slots[i]);
            g_slots[i] = 0;
        }
    }
    
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    
        AllocateSlots();
    
        // these are exactly like the slots that are allocated by the application.
        DWORD i1 = TlsAlloc();
        DWORD i2 = TlsAlloc();
        DWORD i3 = TlsAlloc();
        DWORD i4 = TlsAlloc();
        
        FreeSlots();
    
        // ....pretend we load the CLR...
        
        // This should now be a low slot
        DWORD i5 = TlsAlloc();
        
    
    	return 0;
    }
    

Properties

Article ID: 939969 - Last Review: October 31, 2007 - Revision: 2.3
APPLIES TO
  • Microsoft .NET Framework 2.0
  • Microsoft .NET Framework 1.1
  • Microsoft .NET Framework 1.0
Keywords: 
kbtshoot kbprb kbexpertiseadvanced KB939969

Give Feedback

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com