使用 QC OTA 12.50.1287.0 在 CoUninitialize 中偶尔挂起

Sporadic Hang in CoUninitialize using QC OTA 12.50.1287.0

我在使用 OTA 与 HPE Quality Center 集成的程序中看到零星的挂起。挂起发生在 CoUninitialize 调用中。从 WinDbg 我看到调用 CoUninitialize 的线程:

0:000> kb
ChildEBP RetAddr  Args to Child              
003bf90c 773715f7 00000002 003bf95c 00000001 ntdll!NtWaitForMultipleObjects+0x15
003bf9a8 75ae1a0c 003bf95c 003bf9d0 00000000 KERNELBASE!WaitForMultipleObjectsEx+0x100
003bf9f0 75da087a 00000002 7efde000 00000000 kernel32!WaitForMultipleObjectsExImplementation+0xe0
003bfa44 75da0b79 0000004c 003bfa9c 00000000 USER32!RealMsgWaitForMultipleObjectsEx+0x14d
003bfa60 0272a772 00000001 003bfa9c 00000000 USER32!MsgWaitForMultipleObjects+0x1f
WARNING: Stack unwind information not available. Following frames may be wrong.
003bfaa8 0272a3fc 003bfad0 029a4494 003bfad0 WebClient!DllUnregisterServer+0xe4b2
003bfab8 027b0c44 00861b20 003bfaec 01397000 WebClient!DllUnregisterServer+0xe13c
003bfad0 02703d1b 0270fbb9 027b1841 003bfaec WebClient!DllUnregisterServer+0x94984
003bfaf8 02704824 003bfb6c 02704832 003bfb18 WebClient+0x3d1b
003bfb18 02704b52 003bfb78 003bfb68 027da660 WebClient+0x4824
003bfb78 77ab92e0 02700000 00000000 00000000 WebClient+0x4b52
003bfb98 77ad965c 0280ea85 02700000 00000000 ntdll!LdrpCallInitRoutine+0x14
003bfc20 77ac3bd6 02700000 003bfc44 7cce4b64 ntdll!LdrpUnloadDll+0x375
003bfc64 77372d32 02700000 003bfd00 003bfc8c ntdll!LdrUnloadDll+0x4a
003bfc74 6e9b334f 02700000 003bfd5c 003bfd5c KERNELBASE!FreeLibrary+0x15
003bfc8c 7705c10b 02700000 003bfcac 7705c1e1 nvd3d9wrap!GetNVDisplayW+0x16ff
003bfc98 7705c1e1 00000006 02700000 00000000 ole32!FreeLibraryWithLogging+0x20 [d:\w7rtm\com\ole32\common\loadfree.cxx @ 190]
003bfcac 7705c1f5 003bfcd4 00000000 771682d8 ole32!CClassCache::CDllPathEntry::CFinishObject::Finish+0x32 [d:\w7rtm\com\ole32\com\objact\dllcache.cxx @ 3394]
003bfcc0 7705c2ef 003bfd5c 003bfce0 003bfcd4 ole32!CClassCache::CFinishComposite::Finish+0x1d [d:\w7rtm\com\ole32\com\objact\dllcache.cxx @ 3504]
003bfd6c 7705c17c 7705c5bf 7efde000 00846880 ole32!CClassCache::CleanUpDllsForProcess+0x1b7 [d:\w7rtm\com\ole32\com\objact\dllcache.cxx @ 5784]
003bfd70 7705c5bf 7efde000 00846880 00000000 ole32!ProcessUninitialize+0x37 [d:\w7rtm\com\ole32\com\class\compobj.cxx @ 957]
003bfd84 770688e8 003bfd9c 00000000 003bfee0 ole32!wCoUninitialize+0x1af [d:\w7rtm\com\ole32\com\class\compobj.cxx @ 2813]
003bfda0 00127326 dfcad885 00000000 00000000 ole32!CoUninitialize+0x72 [d:\w7rtm\com\ole32\com\class\compobj.cxx @ 2620]
003bfeec 00124a49 00000001 00844450 0084b220 qctst!wmain+0x2f6 [c:\pd\livemodel\portland\code\tools\qctst\qctst.cpp @ 77]
003bff3c 00124c3d 003bff50 75ae338a 7efde000 qctst!__tmainCRTStartup+0x199 [f:\dd\vctools\crt\crtw32\dllstuff\crtexe.c @ 623]
003bff44 75ae338a 7efde000 003bff90 77ab9882 qctst!wmainCRTStartup+0xd [f:\dd\vctools\crt\crtw32\dllstuff\crtexe.c @ 466]
003bff50 77ab9882 7efde000 7cce4890 00000000 kernel32!BaseThreadInitThunk+0xe
003bff90 77ab9855 001210dc 7efde000 00000000 ntdll!__RtlUserThreadStart+0x70
003bffa8 00000000 001210dc 7efde000 00000000 ntdll!_RtlUserThreadStart+0x1b

这次通话:

003bfa60 0272a772 00000001 003bfa9c 00000000 USER32!MsgWaitForMultipleObjects+0x1f

显示线程正在等待单个句柄。在 003bfa9c 处转储内存显示句柄:

003bfa9c  00000344 77a9fa19 029a4494 003bfab8

句柄显示为:

0:000> !handle 344 f
Handle 344
  Type          Thread
  Attributes    0
  GrantedAccess 0x1fffff:
         Delete,ReadControl,WriteDac,WriteOwner,Synch
         Terminate,Suspend,Alert,GetContext,SetContext,SetInfo,QueryInfo,SetToken,Impersonate,DirectImpersonate
  HandleCount   4
  PointerCount  7
  Name          <none>
  Object Specific Information
    Thread Id   3d14.4694
    Priority    10
    Base Priority 0
    Start Address 2704c04 WebClient

查看我们正在等待的线程的堆栈:

0:012> kb
ChildEBP RetAddr  Args to Child              
0510fad4 773714ab 00000310 00000000 0510fb1c ntdll!ZwWaitForSingleObject+0x15
0510fb40 75ae1194 00000310 00004e20 00000000 KERNELBASE!WaitForSingleObjectEx+0x98
0510fb58 75ae1148 00000310 00004e20 00000000 kernel32!WaitForSingleObjectExImplementation+0x75
0510fb6c 02772b6a 00000310 00004e20 00000000 kernel32!WaitForSingleObject+0x12
WARNING: Stack unwind information not available. Following frames may be wrong.
0510fbb0 0272a255 0510fbc4 0272a25f 0510fbe8 WebClient!DllUnregisterServer+0x568aa
0510fbe8 02704c2e 0510fc38 02704704 0510fbfc WebClient!DllUnregisterServer+0xdf95
0510fbfc 75ae338a 029a59a8 0510fc48 77ab9882 WebClient+0x4c2e
0510fc08 77ab9882 029a59a8 79e54b48 00000000 kernel32!BaseThreadInitThunk+0xe
0510fc48 77ab9855 02704c04 029a59a8 00000000 ntdll!__RtlUserThreadStart+0x70
0510fc60 00000000 02704c04 029a59a8 00000000 ntdll!_RtlUserThreadStart+0x1b

显示它正在等待句柄 310,它是:

0:012> !handle 310 f
Handle 310
  Type          Event
  Attributes    0
  GrantedAccess 0x1f0003:
         Delete,ReadControl,WriteDac,WriteOwner,Synch
         QueryState,ModifyState
  HandleCount   3
  PointerCount  7
  Name          \Sessions\BaseNamedObjects\MainThreadInvokerExecuteEvent
  Object Specific Information
    Event Type Auto Reset
    Event is Waiting

这对我来说就像一个死锁:线程 A 正在等待线程 B。线程 B 正在等待一个事件。如果线程 A 负责发出事件信号,那么我们就会陷入僵局。

源代码:

int _tmain(int argc, _TCHAR* argv [])
{
  CoInitialize(NULL);

  OTACLIENT::ITDConnection11* connection = nullptr;


  if (SUCCEEDED(CoCreateInstance(
    __uuidof(OTACLIENT::TDConnection),
    nullptr,
    CLSCTX_INPROC_SERVER,
    __uuidof(OTACLIENT::ITDConnection11),
    (LPVOID*) &connection)))
  {
    if (SUCCEEDED(connection->InitConnectionEx(URL)))
    {
      if (SUCCEEDED(connection->Login(USERNAME, PASSWORD)))
      {
        if (SUCCEEDED(connection->Connect(DOMAIN, PROJECT)))
        {
          connection->Disconnect();
        }

        connection->Logout();
      }

      connection->ReleaseConnection();
    }

    connection->Release();
    connection = nullptr;
  }

  CoUninitialize();

    return 0;
}

非常感谢有关如何进一步调查此问题的建议。

我的问题的答案是升级到 QC 12.50 补丁 1。