如何从任何线程安全地使用 exit()
How to use exit() safely from any thread
根据手册页 (2),exit
函数不是线程安全的:MT-Unsafe race:exit
,这是因为此函数试图清理资源(将数据刷新到磁盘、关闭文件描述符等...) 通过调用使用 on_exit
和 atexit
注册的回调。我希望我的程序能够做到这一点! (我的一个线程在整个程序的生命周期中保持 fd 打开,所以 _exit
不是我的选择,因为我希望所有数据都写入输出文件)
我的问题如下:如果我很小心并且不在我的线程之间共享任何敏感数据(如 fd),是否 "acceptable" 调用 exit
多线程程序?请注意,如果发生不可恢复的错误,我只会调用 exit
。然而,当程序试图退出时,我不能承受段错误。问题是,任何线程都可能发生不可恢复的错误...
我正在考虑使用 setjmp/longjmp 来终止我的线程 "nicely" 但这将非常复杂,并且需要在我的代码中进行许多更改。
如有任何建议,我们将不胜感激。谢谢 ! :)
编辑: 感谢@Ctx 启蒙,我想出了以下想法:
#define EXIT(status) do { pthread_mutex_lock(&exit_mutex); exit(status); } while(0)
当然 exit_mutex 必须是全局的(外部)。
联机帮助页指出
The exit() function uses a global variable that is not protected, so it is not thread-safe.
因此,如果您以任何方式小心,它也无济于事。
但记录的问题是竞争条件:MT-Unsafe race:exit
因此,如果您确定永远不会从两个线程同时调用 exit()
,那么您应该是安全的!例如,您可以使用互斥锁来确保这一点。
这是不可能的:即使一开始线程之间没有共享数据,数据也必须在线程和它的清理函数之间共享。该函数应该 运行 只有在线程停止或到达安全点后。
现代跨平台 C++
解决方案可以是:
#include <cstdlib>
#include <mutex>
std::mutex exit_mutex;
[[noreturn]] void exit_thread_safe(const int status)
{
exit_mutex.lock();
exit(status);
}
mutex
确保 exit 永远不会被 2 个(或更多)不同的线程调用。
但是,我仍然质疑甚至关心这个背后的原因。对 exit()
的多线程调用的可能性有多大?哪些坏事甚至可能实际发生?
编辑:
使用 std::quick_exit
可避免 clang 诊断警告。
根据手册页 (2),exit
函数不是线程安全的:MT-Unsafe race:exit
,这是因为此函数试图清理资源(将数据刷新到磁盘、关闭文件描述符等...) 通过调用使用 on_exit
和 atexit
注册的回调。我希望我的程序能够做到这一点! (我的一个线程在整个程序的生命周期中保持 fd 打开,所以 _exit
不是我的选择,因为我希望所有数据都写入输出文件)
我的问题如下:如果我很小心并且不在我的线程之间共享任何敏感数据(如 fd),是否 "acceptable" 调用 exit
多线程程序?请注意,如果发生不可恢复的错误,我只会调用 exit
。然而,当程序试图退出时,我不能承受段错误。问题是,任何线程都可能发生不可恢复的错误...
我正在考虑使用 setjmp/longjmp 来终止我的线程 "nicely" 但这将非常复杂,并且需要在我的代码中进行许多更改。
如有任何建议,我们将不胜感激。谢谢 ! :)
编辑: 感谢@Ctx 启蒙,我想出了以下想法:
#define EXIT(status) do { pthread_mutex_lock(&exit_mutex); exit(status); } while(0)
当然 exit_mutex 必须是全局的(外部)。
联机帮助页指出
The exit() function uses a global variable that is not protected, so it is not thread-safe.
因此,如果您以任何方式小心,它也无济于事。
但记录的问题是竞争条件:MT-Unsafe race:exit
因此,如果您确定永远不会从两个线程同时调用 exit()
,那么您应该是安全的!例如,您可以使用互斥锁来确保这一点。
这是不可能的:即使一开始线程之间没有共享数据,数据也必须在线程和它的清理函数之间共享。该函数应该 运行 只有在线程停止或到达安全点后。
现代跨平台 C++
解决方案可以是:
#include <cstdlib>
#include <mutex>
std::mutex exit_mutex;
[[noreturn]] void exit_thread_safe(const int status)
{
exit_mutex.lock();
exit(status);
}
mutex
确保 exit 永远不会被 2 个(或更多)不同的线程调用。
但是,我仍然质疑甚至关心这个背后的原因。对 exit()
的多线程调用的可能性有多大?哪些坏事甚至可能实际发生?
编辑:
使用 std::quick_exit
可避免 clang 诊断警告。