在套间之间传递原始未列集的接口指针引起的死锁

  60 Id: 15fc.2124 Suspend: 1 Teb: 7ef06000 Unfrozen
ChildEBP RetAddr Args to Child
1140e4bc 770b8dcd 00000880 00000000 00000000 ntdll!ZwWaitForSingleObject+0x15
1140e520 770b8d98 00000000 00000000 021fafd4 ntdll!RtlpWaitOnCriticalSection+0x155
1140e548 75189ef4 01a9cb24 00000000 01a9fc28 ntdll!RtlEnterCriticalSection+0x152
1140e560 74c76f74 021fafd4 74cd68b4 1140f3a8 msdart!UMSEnterCSWraper+0x57
1140e568 74cd68b4 1140f3a8 01a9fc28 00000001 msado15!CSemExclusive::Lock+0x13
1140e5a0 0042c08f 01a9fc28 1140ea78 1140f3a8 msado15!CRecordset::Close+0x67
1140e5cc 0042bd88 1140ea78 75583e20 1140f318 ESServer!CDataBase::RecordClose+0x8f [C:\6694_dev\EPol\EPolServer\DataBase.cpp @ 253]
1140e614 0044a90d 1140e678 0e6250f7 00000000 ESServer!CDataBase::RecordRead+0x28 [C:\6694_dev\EPol\EPolServer\DataBase.cpp @ 215]
1140ea80 0042faa7 00000000 00000000 0e6250f7 ESServer!CDataRule::GetNetrangeID+0x8d [C:\6694_dev\EPol\EPolServer\DataRule.cpp @ 8040]
1140f0b0 0041c1de 00000000 1140fc4c 005fd548 ESServer!CDataRule::GetOptRuleNew+0x57 [C:\6694_dev\EPol\EPolServer\DataRule.cpp @ 3433]
1140fc74 00410f3a 1140ff00 00410c00 0b05fca9 ESServer!CCS::SSL_DownloadRule3+0xd9e [C:\6694_dev\EPol\EPolServer\CS.cpp @ 6332]
1140ff88 7544eccb 005fd548 1140ffd4 770fd24d ESServer!CCS::SSL_DownloadProcess+0x5aa [C:\6694_dev\EPol\EPolServer\CS.cpp @ 2531]
1140ff94 770fd24d 0af09d88 dd2a2bfc 00000000 kernel32!BaseThreadInitThunk+0xe
1140ffd4 770fd45f 00410990 0af09d88 ffffffff ntdll!__RtlUserThreadStart+0x23
1140ffec 00000000 00410990 0af09d88 00000000 ntdll!_RtlUserThreadStart+0x1b

  34 Id: 15fc.7d0 Suspend: 1 Teb: 7ef3f000 Unfrozen
ChildEBP RetAddr Args to Child
09d8f64c 770b8dcd 000004e0 00000000 00000000 ntdll!ZwWaitForSingleObject+0x15
09d8f6b0 770b8d98 00000000 00000000 09d8f710 ntdll!RtlpWaitOnCriticalSection+0x155
09d8f6d8 0042b442 005fc348 01c900d0 00000000 ntdll!RtlEnterCriticalSection+0x152
09d8f700 0053c044 00000000 00000000 005a1d1c ESServer!CDataBase::CDataBase+0x1a2 [C:\6694_dev\EPol\EPolServer\DataBase.cpp @ 47]
09d8fd40 0053f4a6 01c900a9 00000001 01c29f40 ESServer!CSuperiorReport::SetOnline+0x54 [C:\6694_dev\EPol\EPolServer\SuperiorReport.cpp @ 1056]
09d8fe3c 0053ee50 0a932b98 09d8fea0 0b1485b0 ESServer!CSuperiorReport::HandleSubord_Base+0x3a6 [C:\6694_dev\EPol\EPolServer\SuperiorReport.cpp @ 1596]
09d8ff20 0053aaad 0a932b98 0af9c9e8 00000000 ESServer!CSuperiorReport::analyseXml_Subordinate+0x2e0 [C:\6694_dev\EPol\EPolServer\SuperiorReport.cpp @ 1544]
09d8ff88 7544eccb 01c29f40 09d8ffd4 770fd24d ESServer!CSuperiorReport::MainThread+0x18d [C:\6694_dev\EPol\EPolServer\SuperiorReport.cpp @ 796]
09d8ff94 770fd24d 01c29f40 c5b22bfc 00000000 kernel32!BaseThreadInitThunk+0xe
09d8ffd4 770fd45f 0053a920 01c29f40 ffffffff ntdll!__RtlUserThreadStart+0x23
09d8ffec 00000000 0053a920 01c29f40 00000000 ntdll!_RtlUserThreadStart+0x1b


-----------------------------------------
DebugInfo = 0x00704800
Critical section = 0x005fc348 (ESServer!gDBabc+0x0)
LOCKED
LockCount = 0x5
WaiterWoken = No
OwningThread = 0x00002124
RecursionCount = 0x1
LockSemaphore = 0x4E0
SpinCount = 0x00000000
-----------------------------------------

-----------------------------------------
DebugInfo = 0x007314c8
Critical section = 0x01a9cb24 (+0x1A9CB24)
LOCKED
LockCount = 0x1
WaiterWoken = No
OwningThread = 0x000007d0
RecursionCount = 0x2
LockSemaphore = 0x880
SpinCount = 0x00000000
-----------------------------------------
 
 
不要在套间之间传递原始未列集的接口指针

设想编写一个有两个线程的COM客户端。两个线程都调用CoInitialize进入一个STA,然后其中一个线程——线程A,使用CoCreateInstance创建一个COM对象。线程A想要与线程B共享从CoCreateInstance返回的接口指针。所以线程A将接口指针赋值给一个全局变量,然后通知线程B指针已经准备好了。线程B从全局变量读取接口指针并且对对象发起调用。这个过程有什么错误吗?

这个过程会引发事故。问题是线程A向其他套间中的线程传递了原始未列集的接口指针。线程B应该只通过列集到线程B所属套间的接口指针与对象通信。

这里"列集(Marshaling)"的意思是给COM在线程B所属套间中创建新代理的机会,让线程B可以安全地进行调用。在套间之间传递原始接口指针的后果可以从与时间极其相关(也很难重现)的数据损坏到完全死锁。
 
单线程公寓实现同步,有很多COM库的干预,包括将外部的调用转化成窗口消息,然后那个特别的隐藏窗口的窗口函数把窗口消息转化成COM对象的函数调用。这样的模型可以减小开发组件的难度,可是,却牺牲了效率。多线程公寓把实现同步任务全部交给了组件自己,所以在这种公寓中生存的COM对象必须足够健壮,考虑各种同步问题,不至于多个线程在调用对象的成员函数时会打架。
 
参考:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值