首页 > 解决方案 > 如何处理第三方代码中的死锁

问题描述

我们有一个第三方方法Foo,它有时会因为未知原因而陷入死锁。

我们正在执行一个单线程 tcp-server 并每 30 秒调用一次此方法以检查外部系统是否可用。

为了缓解第三方代码中的死锁问题,我们将 ping-call 放在了Task.Runto 中,这样服务器就不会死锁。

喜欢

async Task<bool> WrappedFoo()
{
    var timeout = 10000; 

    var task = Task.Run(() => ThirdPartyCode.Foo());
    var delay = Task.Delay(timeout);

    if (delay == await Task.WhenAny(delay, task ))
    {
        return false;
    }
    else
    {
        return await task ;
    }
}

但这(在我们看来)有可能使自由线程的应用程序匮乏。因为如果一次调用ThirdPartyCode.Foo死锁,线程将永远无法从这个死锁中恢复,如果这种情况经常发生,我们可能会耗尽资源。

是否有一种通用方法应该如何处理死锁的第三方代码?

ACancellationToken不起作用,因为第三方 api 不提供任何取消选项。

更新: 手头的方法是从 SAP 提供的 SAPNCO.dll 中建立和测试到 sap 系统的 rfc 连接,因此该方法不是简单的网络 ping。我重命名了问题中的方法以避免进一步的误解

标签: c#deadlock.net-5

解决方案


是否有一种通用方法应该如何处理死锁的第三方代码?

是的,但这并不容易或简单。

行为不端的代码的问题在于它不仅会泄漏资源(例如,线程),而且还可以无限期地持有重要资源(例如,一些内部“句柄”或“锁”)。

强制回收线程和其他资源的唯一方法是结束进程。该操作系统用于清理行为不端的进程,并且非常擅长。因此,这里的解决方案是启动一个子进程来进行 API 调用。您的主应用程序可以通过重定向 stdin/stdout 与其子进程通信,如果子进程超时,主应用程序可以终止它并重新启动它。

不幸的是,这是取消不可取消代码的唯一可靠方法。


推荐阅读