鉴于:
- 在终结器中获取锁可能会导致死锁
- 终结器可以抛出异常
在未处理的异常处理程序中获取锁是否安全,或者下面的代码会导致死锁吗?
static void Main(string[] args)
{
AppDomain.CurrentDomain.UnhandledException +=
new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
//do other stuff
}
private static object loggingLock = new object();
static void CurrentDomain_UnhandledException(
object sender,
UnhandledExceptionEventArgs e)
{
lock (loggingLock)
{
//log the exception
}
}
最佳答案
Given that:
- taking a lock while in a finalizer can cause deadlocks
- finalizers can throw exceptions
编辑事实证明,根据定义,终结器中抛出的异常是致命的:
doc: If Finalize or an override of Finalize throws an exception, and the runtime is not hosted by an application that overrides the default policy, the runtime terminates the process and no active try-finally blocks or finalizers are executed. This behavior ensures process integrity if the finalizer cannot free or destroy resources.
See also c# finalizer throwing exception?
注意:即使异常可能源自函数内部,但这并不意味着它将在该函数的上下文中进行处理。事实上,堆栈将被展开:
doc: An exception is unhandled only if the entire stack for the thread has been unwound without finding an applicable exception handler, so the first place the event can be raised is in the application domain where the thread originated.
我不明白为什么锁定不安全。 (通常的警告适用:在持有锁时不要执行阻塞操作...)。
但是,您可能需要在此处重新考虑可重入性和无限递归:
您将如何应对日志记录时的错误? 根据定义将获取锁,因为线程已经持有它。但是日志代码是可重入的吗?即:调用另一个 log 操作会扰乱正在进行的(失败/失败)操作的状态吗?日志记录可能吗?
--> 如果不允许重入(或需要特殊操作(例如在其他地方记录),即使获取了锁,您也需要显式的“inLoggingOperation”标志,因为锁不会阻止单线程重入
小要点:如果您的日志记录不完全防异常,那么当您已经处于 CurrentDomain.UnhandledException 中时,您可能会遇到麻烦(AFAICT the docs do not describe 在事件处理程序中引发异常时会发生什么)。
关于c# - 锁定未处理的异常处理程序是否安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12630042/