如何正确终止 dll 中的挂起线程?

Posted

技术标签:

【中文标题】如何正确终止 dll 中的挂起线程?【英文标题】:How to terminate a hanging thread inside a dll correctly? 【发布时间】:2009-06-17 01:30:08 【问题描述】:

大家好,

我有一个包含错误的第三方库。当我调用一个函数时,它可能会挂起。库函数在 dll 中调用。我决定将调用移到线程中并等待一段时间。如果线程已完成,则 OK。如果不是 - 我应该强制终止它。

这里的简化示例:

unsigned Counter = 0;
void f()

    HANDLE hThread;
    unsigned threadID;

    // Create the second thread.
    hThread = (HANDLE)_beginthreadex( NULL, 0, DoSomething, NULL, 0, &threadID );

    if (WAIT_TIMEOUT == WaitForSingleObject( hThread, 5000 ))
    
        TerminateThread(hThread, 1);    
        wcout << L"Process is Timed Out";
    
    else
    
        wcout << L"Process is Ended OK";
    

    CloseHandle(hThread);   

    wcout << Counter;


unsigned int _stdcall DoSomething( void * /*dummy*/ )

    while (1)
    

        ++Counter;

    
    _endthreadex( 0 );
    return 0;

问题

    TerminateThread()函数不建议调用。 正如我之前提到的,线程在 在 dll 中运行。如果我使用 TerminateThread() 终止线程,我的 dll 将不会使用 FreeLibrary() 甚至 FreeLibraryAndExitThread() 卸载。两个函数都挂起。

如何终止线程并保持 FreeLibrary() 正常工作?

谢谢。

【问题讨论】:

也许你应该考虑在一个单独的进程中托管 rouge dll,如果东西变成梨形就终止进程? 【参考方案1】:

很遗憾,您不能随意安全地终止线程。

TerminateThread 导致线程立即终止,即使线程正在持有锁或修改某些内部状态。 TerminateThread 可能会导致您的应用程序随机挂起(如果线程持有锁)或崩溃(如果线程正在修改某些状态并且它保持不一致)

如果您不能信任 DLL 的正确行为并且这会给您带来严重的可靠性问题,您应该将调用 DLL 的代码移动到一个单独的进程中 - 终止一个进程会更安全。

【讨论】:

对突然终止线程的陷阱的深刻见解。 谢谢,我会尝试尝试您的建议。 我希望我能在处理生产系统后两次投票,因为人们认为线程可能会被终止。 即使 Windows 确实释放了线程在其令人震惊的死亡过程中可能持有的任何资源,它仍然可能会导致 application-level 不一致...

以上是关于如何正确终止 dll 中的挂起线程?的主要内容,如果未能解决你的问题,请参考以下文章

C++多线程编程——线程的挂起唤醒与终止

检测终止的挂起应用程序

Kotlin 协程协程的挂起和恢复 ② ( 协程挂起 和 线程阻塞 对比 )

Kotlin 协程协程的挂起和恢复 ② ( 协程挂起 和 线程阻塞 对比 )

你应该知道的协程中的挂起转化小技巧

你应该知道的协程中的挂起转化小技巧