检查分离的 pthread 是否仍然存在?

Check whether a detached pthread is still alive?

我正在为一个多线程套接字编程项目使用 POSIX 个线程。我有 运行 需要使用 setdetachstate() 从主程序中分离线程的情况;但是,稍后我取消了线程(我知道取消通常是不好的做法,但我知道我在做什么(希望如此))。我需要一种方法来检查线程是否仍然存在,经过一些研究后,我发现即使我有 TID 而不是 PID,waitpid() 也可能适合我的目的。然而,在尝试之后,无论是否使用 ptraces,它都不起作用。另一种我在网上到处看到的方法是pthread_join()。虽然我同意这是最佳方式,但正如我所说,我的线程已分离,因此无法加入。

附带说明一下,我的目标是找到一种方法来等待函数调用 pthread_cancel() 完成,然后再执行任何后续代码,即

pthread_t tid;
// ...
pthread_cancel(tid);
// wait until pthread with ID tid is cancelled
// more code here...

最初,我需要检查分离的 pthread 是否存在的原因是因为我打算做这样的事情:while(!pthread_dead(tid)); 或类似的事情;但是,如果有直接等待取消完成的解决方案,那就更好了。请尽量不要批评我使用分离线程或 pthread 取消;我已经考虑了许多行动计划,无论我如何去做,这似乎都是必需的(除非我正在做一个我不想做的多进程应用程序)。除非我在做一些在语法或结构上绝对令人厌恶的事情,否则如果你能回答我的问题,我将不胜感激。

谢谢!

P.S。我正在用 C++ 编写代码。

您是否考虑过使用 Actor 模型编程,或者更好的通信顺序进程?

当你有一个单独的线程需要关闭并做自己的事情时,这些确实是一个很好的模型,你需要能够告诉它一些事情并得到回应。

您显然需要知道异步操作已经完成(单独线程的终止)——让该线程向您发送其终止的直接确认没有错,而不是试图确定是否或不是它通过 waitpid() 等稍微不稳定的方式仍然存在。假设您选择 ZeroMQ 作为您的 Actor 模型库;对于 "kill" 那个分离的线程,你会向它发送一个 ZeroMQ "socket" 的命令。收件人线程将收到该消息,理解它的意思是 "die",并在终止自身之前做任何它需要的清理工作。就在它自己终止之前,它会在另一个 "socket" 上向您发回确认,是的,它已经死了(或者至少即将死去,所有必要的清理工作已经发生)。

Actor 模型/CSP 编程强调有一个循环来响应来自一个或多个源的消息。嗯,你自己的代码片段提示一个循环,等待pthread_cancel()生效。

我把 "socket" 放在引号中,因为 ZeroMQ 套接字下面可以是 tcp 套接字、ipc、一些进程内内存传输等;一切都一样。进程内处理自然非常快。

Actor 模型和通信顺序进程的区别在于,在 Actor 模型中,当消息被发送时,发送方没有可用的信息表明它已经收到,而在通信顺序进程中,成功发送 = 完成读。就个人而言,我更喜欢后者——这样您的代码就可以完全了解消息接收者的去向;一个 send/receive 是一个 Execution Rendezvous。因此,当您发送 "terminate" 消息时,您可以确定收件人线程已收到消息并正在对其进行操作。当接收方发送它的 "I'm dead" 确认时,它知道命令线程已收到该确认。

仅供参考,CSP 在实时系统中非常有用,不是因为它更快,而是因为您的程序可以更好地了解它是否跟上实时需求。 Actor 模型让您可以 "hide" 实时不足,如通信链路中的延迟。