DLL_PROCESS_ATTACH Deadlock

本文探讨了Windows DLL加载器中DLL_PROCESS_ATTACH事件可能导致的死锁问题,特别是在调用需要同步的函数时。作者建议避免在此阶段进行任何可能引起同步操作的行为。

转载自:http://blogs.msdn.com/mgrier/archive/2005/06/21/431378.aspx

另一篇:http://www.osronline.com/ddkx/ddtools/dv_8pkj.htm

The NT DLL Loader: DLL callouts (DllMain) - DLL_PROCESS_ATTACH deadlocks

The Windows DLL loader (I wasn't around then but I assume some of this even comes from the days of 16-bit Windows) has a feature where a DLL may have an "entry point".

If a DLL has an entry point, the loader calls into it on certain significant events.  These events have identifiers associated with them:

  • DLL_PROCESS_ATTACH
  • DLL_PROCESS_DETACH
  • DLL_THREAD_ATTACH
  • DLL_THREAD_DETACH

I'm not going to talk about the thread callouts any time soon; they probably don't do what you expect them to do so for the most part you should call the function DisableThreadLibraryCalls() in your DLL_PROCESS_ATTACH to save extra page faults when threads come and go.

The apparent contract for DLL_PROCESS_ATTACH is that it is called before any code in your DLL can be called.  Sounds like a nice place to do one-time initialization that couldn't be static for some reason.

Note that I said "apparent".  Due to the previous articles, if you are involved in a cycle, you can have your code called before your DLL_PROCESS_ATTACH callout has been issued.  Maybe you're lucky and you've never been hit by this.  There are a lot of lucky people out there.

I'm going to paint a contractual picture here, assuming no cycles are involved.

Presumably if one thread is in the middle of calling your DLL_PROCESS_ATTACH, any other thread that wants to access the exports of your DLL has to block waiting for you to finish your initialization.  Let's call this the "mythical loader lock".  Maybe it's not so mythical and we can discuss/debate the scope of the synchronization (all DLLs, only the DLLs waiting to initialize, what about cycles?) but let's work out the invariants of the contract before we get too hung up on implementation details.

Thus the first problem with DLL_PROCESS_ATTACH processing is deadlocks.  A great example of this is calling CreateThread() inside your own DLL_PROCESS_ATTACH to start a thread running code for your DLL.  Clearly the new thread can't start running your code until you have finished your DLL_PROCESS_ATTACH because otherwise we would be breaking the contract.  Thus the new thread has to wait for you to exit your DllMain().  Maybe that's OK; if it can just suspend waiting for you to finish up, maybe it fired up and immediately had to block waiting for synchronization but if it doesn't happen too frequently, you can survive this.

But now imagine that you do something nifty and useful in that worker thread.  Someday someone comes along and wants to queue a work item to that thread and wait for it to complete.  Boom.  Insta-deadlock.

That's an easy example, but basically the rule is this:

Calling any function from within your DLL_PROCESS_ATTACH which requires synchronization can deadlock.

Obviously it doesn't have to deadlock; a lot of folks get away with a lot of bad stuff.  They're getting lucky for the most part.

A great example is the process heap.  Did you know that you can lock it?  You can!  You can probably have a lot of fun by calling HeapLock(GetProcessHeap())?  Why would you do that?  I don't know!  Who can know?  Can we stop it?  People want to but just wait for the black helicopter crowd to show up saying that it's really a collusion/conspiracy to get people to upgrade software on Windows.

If someone locks it (or maybe calls HeapWalk on the process heap which I assume locks it for the duration of the walk) and then calls into the loader... well... boom.  You're deadlocked.

Those are two easy cases.  Clearly you can deadlock in additional ways (RPC calls to another process or machine which have to reenter your process on a different thread which then might need the Mythical Loader Lock) and being creative with things like the thread pool, windows messages, etc. you can come up with a million variations on the theme.

Thus, DLL_PROCESS_ATTACH rule #1:

Don't do anything that requires synchronization.  Currently, even heap allocation is suspect.

Published Tuesday, June 21, 2005 9:48 PM by mgrier

Comments

# re: The NT DLL Loader: DLL callouts (DllMain) - DLL_PROCESS_ATTACH deadlocks
Wednesday, June 22, 2005 1:19 AM by Heath Stewart
A good rule of thumb is to not do anything. Windows Script has suffered a few times because automation objects weren't released before the host shuts down the script engine. GC'ing those objects may also unload DLLs, like we see in managed code. Violá - deadlock. It's all tricky business when considering what can and can't be done in DllMain, so as little as possible should be done - if anything.
# re: The NT DLL Loader: DLL callouts (DllMain) - DLL_PROCESS_ATTACH deadlocks
Wednesday, June 22, 2005 9:34 AM by Russ Osterlund
Although a tad "dated", people might want to check out my notes on the loader lock in Windows SP (SP1) located at www.smidgeonsoft.com. This is a collection of notes and references to the loader lock found by searching the system DLLs. It is interesting to note that there are two exported NTDLL functions, LdrLockLoaderLock and LdrUnlockLoaderLock, that make life "interesting".
# re: The NT DLL Loader: DLL callouts (DllMain) - DLL_PROCESS_ATTACH deadlocks
Wednesday, June 22, 2005 10:33 AM by LarryOsterman
*Makes a note to self: File a bug to have those exports removed*

I hope to heaven above that nobody EVER uses those exports.

This is a HIDEOUSLY, HORRIBLE, AWFUL, HIENOUS idea.

It's also not recommended.

Please don't go there.
# re: The NT DLL Loader: DLL callouts (DllMain) - DLL_PROCESS_ATTACH deadlocks
Wednesday, June 22, 2005 2:17 PM by mgrier
I added those exports because instead, people were using an even worse hack to lock the loader lock in various DLLs around the system.

At least this way we can set a breakpoint on the lock call.

These are, of course, undocumented and for internal use only and will go away someday. It was better than the pointer swizzling people were doing.
# re: The NT DLL Loader: DLL callouts (DllMain) - DLL_PROCESS_ATTACH deadlocks
Wednesday, June 22, 2005 4:33 PM by Mike Dimmick
I'll add, don't put global objects of a class that has a constructor or destructor in a DLL. Global objects get constructed by DllMainCRTStartup (the actual entry point if you're going to use the C/C++ runtime) in response to DLL_PROCESS_ATTACH and destroyed in response to DLL_PROCESS_DETACH.

So the same rules apply to these global objects as to DllMain itself.
# re: The NT DLL Loader: DLL callouts (DllMain) - DLL_PROCESS_ATTACH deadlocks
Wednesday, June 22, 2005 5:05 PM by mgrier
I'm gettin' there... I'm gettin' there... people usually do not believe that the restrictions are real so I'm making sure that there is plenty of either obvious behavior of behavior which can be justified based strictly on documented public behavior which will quantify exactly what the dangerous patterns are.
# re: The NT DLL Loader: DLL callouts (DllMain) - DLL_PROCESS_ATTACH deadlocks
Wednesday, June 22, 2005 9:17 PM by Norman Diamond
Wednesday, June 22, 2005 4:33 PM by Mike Dimmick

> I'll add, don't put global objects of a
> class that has a constructor or destructor
> in a DLL.

I have a feeling I've seen that warning before. But one place I _haven't_ seen it is in the output of a VC++ compiler. Anyone know why not? Compilers know when they're building DLLs and they know when the source code has global objects with constructors or destructors, so compilers ought to know that the programmer needs to be warned.
# re: The NT DLL Loader: DLL callouts (DllMain) - DLL_PROCESS_ATTACH deadlocks
Wednesday, June 22, 2005 10:10 PM by mgrier
There is hope for C++ global object construction if we could nix the idea of data exports.

When we get to the phase about talking about the ramifications of DLL_PROCESS_DETACH, we'll see that it's actually the rundown that's harder to solve.
# re: The NT DLL Loader: DLL callouts (DllMain) - DLL_PROCESS_ATTACH deadlocks
Tuesday, June 28, 2005 11:17 AM by Ron Hancock
Apologies but I really don't have that much idea of the detail that is being discussed. However I have just experienced a problem that I can not remove and it appears relevant to the general discussion. I use Win 2000 Pro (with all updates) and I am now getting the following error message during boot:

"The procedure entry point LdrLockLoaderLock could not be located in the dynamic link library ntdll.dll"

The header on the error mentions ctfmon.exe at this point but I also get a similar error from all sorts of other applications.

And now the question. Having got this how do I get rid of it? I was running synchronization but have turned this off.

If you can help I'd be very grateful. I'm fairly clued in on using PCs but I am not a programmer.
# re: The NT DLL Loader: DLL callouts (DllMain) - DLL_PROCESS_ATTACH deadlocks
Tuesday, June 28, 2005 2:14 PM by mgrier
That executable requires a feature that is present only on Windows XP and later. It cannot run on Windows 2000.
# re: The NT DLL Loader: DLL callouts (DllMain) - DLL_PROCESS_ATTACH deadlocks
Tuesday, June 28, 2005 6:00 PM by Seth McCarus
"Don't do anything that requires synchronization. Currently, even heap allocation is suspect."

MSDN explicitly allows InitializeCriticalSection in DllMain, but I'm pretty sure that allocates heap memory...
# re: The NT DLL Loader: DLL callouts (DllMain) - DLL_PROCESS_ATTACH deadlocks
Tuesday, June 28, 2005 7:51 PM by mgrier
Re: InitializeCriticalSection() allocating heap:

Only on chk builds or if the app verifier is on. On the other hand, do the docs say "does not take any additional synchronization or make callbacks forever into the future?"?

I'm just saying it's suspect. As long as someone hasn't called HeapWalk(), most of the process default heap's allocations actually come from lookaside lists which don't acquire the heap's lock in any case (which possibly violates the HeapLock() contract...) and so would never deadlock.

As in the theme for my blog, this probably works 99.9% of the time. Is that OK? Do you want to fly on a plane that's run by a control system that's 99.9% reliable or do you want to pay for a few more 9s? How about your banking? Email? online RPG? Online picture archives?
# re: The NT DLL Loader: DLL callouts (DllMain) - DLL_PROCESS_ATTACH deadlocks
Sunday, July 10, 2005 6:22 PM by Eugene Gershnik
> for the most part you should call the
> function DisableThreadLibraryCalls() in your > DLL_PROCESS_ATTACH to save extra page faults
> when threads come and go.

Isn't this a bad advice for folks that use statically linked C runtime? AFAIK it cleans up its per-thread data structures on thread detach notifications.
# mgrier s WebLog The NT DLL Loader DLL callouts DllMain | pool toys

转载于:https://www.cnblogs.com/taoxu0903/archive/2009/07/05/1517337.html

<think>好的,用户问的是如何在MySQL中启用innodb_deadlock_detect配置。首先,我需要确认这个参数的作用和默认值。根据引用[3],这个参数的默认值是on,也就是启用的。但可能用户想确认如何手动设置或者检查当前状态。 接下来,我应该分步骤说明如何启用。通常MySQL的配置可以通过设置全局变量或者修改配置文件。动态设置的话,使用SET GLOBAL命令,但需要SUPER权限。另外,修改my.cnf或my.ini文件可以让配置永久生效。 还要提到如果用户想关闭死锁检测,可以设置为off,但需要注意这时候innodb_lock_wait_timeout会起作用。同时,需要提醒用户权限问题,以及修改配置文件后重启MySQL服务的重要性。 可能用户遇到死锁问题,想确保检测是否开启。所以需要包括检查当前值的步骤,比如SHOW VARIABLES命令。 另外,引用[3]提到启用innodb_deadlock_detect后,死锁会立即回滚,否则依赖超时。这部分信息对用户理解配置的影响很重要,应该在回答中说明。 需要确保回答清晰,步骤明确,并引用相关的参考资料,比如引用[3]和引用[4]中的链接,供用户进一步阅读。</think>要在MySQL中启用InnoDB死锁检测功能,可通过以下步骤实现: ### 配置步骤说明 1. **查看当前状态** 执行SQL命令查看当前配置: ```sql SHOW VARIABLES LIKE 'innodb_deadlock_detect'; ``` 若返回值为`ON`则表示已启用[^3]。 2. **动态启用(无需重启)** 拥有`SUPER`权限的用户可通过全局变量临时启用: ```sql SET GLOBAL innodb_deadlock_detect = ON; ``` 这种方式会立即生效但重启后失效。 3. **永久生效配置** 修改MySQL配置文件`my.cnf`(Linux)或`my.ini`(Windows),在`[mysqld]`段添加: ```ini innodb_deadlock_detect = ON ``` 修改后需重启MySQL服务使配置永久生效。 4. **相关参数说明** - 当`innodb_deadlock_detect=ON`时(默认值),检测到死锁会立即回滚事务 - 若设置为`OFF`,则依赖`innodb_lock_wait_timeout`参数处理锁冲突[^3] ### 注意事项 - 此功能仅作用于InnoDB行级锁,无法检测表级锁造成的死锁[^1][^2] - 建议配合事务隔离级别调整和索引优化来减少死锁发生概率 - 完整的InnoDB锁机制分析可参考锁兼容性矩阵[^4]
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值