Microsoft KB Archive/811591

= A deadlock may occur when more than one client loads a multithreaded apartment singleton object that you created by using Active Template Library =

Article ID: 811591

Article Last Modified on 5/20/2005

-

APPLIES TO


 * Microsoft Visual Studio .NET 2003 Professional Edition
 * Microsoft Visual Studio .NET 2003 Enterprise Architect
 * Microsoft Visual Studio .NET 2003 Enterprise Developer
 * Microsoft Visual Studio .NET 2003 Academic Edition

-



SYMPTOMS
A deadlock may occur when more than one client creates the same multithreaded apartment (MTA) singleton object by using Microsoft Active Template Library (ATL). When the deadlock occurs, any new calls to receive an instance of the singleton object are also in deadlock.



WORKAROUND
To work around this problem, replace the DECLARE_CLASSFACTORY_SINGLETON definition with a definition that uses a fixed implementation of the CComClassFactorySingleton class. Add the following code before the declaration of the Singleton class:


 * 1) undef DECLARE_CLASSFACTORY_SINGLETON
 * 2) define DECLARE_CLASSFACTORY_SINGLETON(obj) DECLARE_CLASSFACTORY_EX(CMyComClassFactorySingleton )

template  class CMyComClassFactorySingleton : public CComClassFactory { public: CMyComClassFactorySingleton : m_hrCreate(S_OK){} virtual ~CMyComClassFactorySingleton{} // IClassFactory STDMETHOD(CreateInstance)(LPUNKNOWN pUnkOuter, REFIID riid, void** ppvObj) {       HRESULT hRes = E_POINTER; if (ppvObj != NULL) {           *ppvObj = NULL; // Aggregation is not supported in singleton objects. ATLASSERT(pUnkOuter == NULL); if (pUnkOuter != NULL) hRes = CLASS_E_NOAGGREGATION; else {               if (m_hrCreate == S_OK && m_spObj == NULL) {                   Lock; __try {                       // Fix:  The following If statement was moved inside the __try statement. // Did another thread arrive here first? if (m_hrCreate == S_OK && m_spObj == NULL) {                           CComObjectCached *p; m_hrCreate = CComObjectCached::CreateInstance(&p); if (SUCCEEDED(m_hrCreate)) {                               m_hrCreate = p->QueryInterface(IID_IUnknown, (void**)&m_spObj); if (FAILED(m_hrCreate)) {                                   delete p;                                } }                       }                    }                    __finally {                       Unlock; }               }                if (m_hrCreate == S_OK) {                   hRes = m_spObj->QueryInterface(riid, ppvObj); }               else {                   hRes = m_hrCreate; }           }        }        return hRes; }   HRESULT m_hrCreate; CComPtr m_spObj; };



STATUS
Microsoft has confirmed that this is a problem in the Microsoft products that are listed in the &quot;Applies to&quot; section.



Step 1: Create a multithreaded apartment server object
 Create a new ATL project by using Microsoft Visual C++ .NET, and name it MTAServer. In the ATL Project Wizard - MTAServer dialog box, click Application Settings, and then clear the Attributed check box. In Solution Explorer, right-click MTAServer, point to Add, and then click Add Class.

The Add Class - MTAServer dialog box appears. Under Templates, click ATL Simple Object, and then click Open.

The ATL Simple Object Wizard - MTAServer dialog box appears.</li> In the Short name box, type MTAObject .</li> Click Options, and then click Free.</li>  Add the following code in the FinalConstruct method of the MTAObject.h file: ::Sleep(20000); </li>  Add the following code in the public access specifier. DECLARE_CLASSFACTORY_SINGLETON(CMTAObject) </li> Build the project to create the MTAServer.dll file.</li></ol>

Step 2: Create a client for the MTAServer application
<ol> Create a Microsoft Windows application by using Microsoft Visual C# .NET, and name it MTAClient.</li> Add a button control to the Form1 form. By default, the button1 button control is created.</li>  Double-click button1, and then add the following code in the button1_Click method: myThreadStart; myThreadStart; myThreadStart; myThreadStart; myThreadStart; myThreadStart; myThreadStart; myThreadStart; myThreadStart; myThreadStart; </li>  Add the myThreadStart method and the ThreadProc method before the button1_Click method: private void myThreadStart {   Thread t = new Thread(new ThreadStart(ThreadProc)); t.ApartmentState = ApartmentState.MTA; t.Start; }

static void ThreadProc {   MTAServerLib.MTAObjectClass x = new MTAServerLib.MTAObjectClass; System.Diagnostics.Debug.WriteLine(&quot;Hello from the thread pool.&quot;); } </li>  Add the following namespace to the beginning of the Form1.cs file: using System.Threading; </li> In Solution Explorer, right-click References, and then click Add Reference.

The Add Reference dialog box appears.</li> Click Browse to locate the MTAServer.dll file that you created in the &quot;Step 1: Create a multithreaded apartment (MTA) server object&quot; section, and then build the solution.</li> Press F5 to run the MTAClient application.</li> After the Form1 form appears, click button1, and then view the output window.</li></ol>

The MTAClient application starts ten threads, but the output window shows only two threads. The other threads are in the deadlock that is mentioned in the &quot;Symptoms&quot; section.

Additional query words: Free Threaded

Keywords: kbtshoot kbbug kbatlserver KB811591

-

[mailto:TECHNET@MICROSOFT.COM Send feedback to Microsoft]

© Microsoft Corporation. All rights reserved.