如何安全终止多线程进程
我正在开发一个项目,我们使用 pthread_create 创建多个子线程。 线程创建逻辑不在我的控制范围内,因为它是由项目的其他部分实现的。
每个线程执行一些需要 30 秒以上才能完成的操作。 在正常情况下,程序运行得很好。 但问题发生在程序终止时。 当我收到 SIGINT 信号时,我需要尽快退出 main。
当我调用 exit() 或从 main 返回时,将调用退出处理程序和全局对象的析构函数。我相信这些操作与正在运行的线程存在竞争条件。我相信存在许多竞争条件,这使得解决所有这些问题变得困难。 我认为有两种解决方案。
- 调用 _exit() 并忘记所有资源的取消分配
- 当 SIGINT 存在时,关闭/杀死所有线程,然后从主线程调用 exit(),这将释放资源。
我认为第一个选项可行,但我不想突然终止该过程。 所以我想知道是否可以尽快终止所有子线程,以便退出处理程序&析构函数可以执行所需的清理任务并终止程序。
我已经阅读了这篇文章,如果您知道其他方法,请告诉我:POSIX API 调用列出进程中运行的所有 pthread
另外,请告诉我是否有任何其他解决方案可以解决此问题
I am working on a project where we have used pthread_create to create several child threads.
The thread creation logic is not in my control as its implemented by some other part of project.
Each thread perform some operation which takes more than 30 seconds to complete.
Under normal condition the program works perfectly fine.
But the problem occurs at the time of termination of the program.
I need to exit from main as quickly as possible when I receive the SIGINT signal.
When I call exit() or return from main, the exit handlers and global objects' destructors are called. And I believe these operations are having a race condition with the running threads. And I believe there are many race conditions, which is making hard to solve all of theses.
The way I see it there are two solutions.
- call _exit() and forget all de-allocation of resources
- When SIGINT is there, close/kill all threads and then call exit() from main thread, which will release resources.
I think 1st option will work, but I do not want to abruptly terminate the process.
So I want to know if it is possible to terminate all child threads as quickly as possible so that exit handler & destructor can perform required clean-up task and terminate the program.
I have gone through this post, let me know if you know other ways: POSIX API call to list all the pthreads running in a process
Also, let me know if there is any other solution to this problem
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在程序退出之前您需要做什么?如果答案是“取消分配资源”,那么您无需担心。如果您调用
_exit
,那么程序将立即退出,操作系统将为您清理所有内容。另请注意,您可以在信号处理程序中安全执行的操作极其有限,因此不建议尝试自行执行任何清理。如果您有兴趣,这里有一个您可以执行的操作此处。但是,例如,您无法将文件刷新到磁盘(这是我能想到的您可能合法地想要在这里做的唯一事情)。那是禁区。
What is it that you need to do before the program quits? If the answer is 'deallocate resources', then you don't need to worry. If you call
_exit
then the program will exit immediately and the OS will clean up everything for you.Be aware also that what you can safely do in a signal hander is extremely limited, so attempting to perform any cleanup yourself is not recommended. If you're interested, there's a list of what you can do here. But you can't flush a file to disk, for example (which is about the only thing I can think of that you might legitimately want to do here). That's off limits.
这是如何定义的?因为当你收到这样的信号时,没有办法“尽快退出”。
您可以设置标志、发布到信号量,或者类似地设置一个状态来告诉其他线程是时候关闭了,或者您可以终止整个进程。
如果您选择设置标志或类似标志来告诉其他线程关闭,则可以设置这些标志并从信号处理程序返回,并希望线程正常运行并且进程干净地关闭。
如果您选择终止线程,那么终止线程、终止进程或调用
_exit()
实际上没有区别。您不妨保持简单并调用_exit()
。当您必须在单个信号处理程序调用中做出决定时,这就是您可以选择的全部内容。选择一个。
更好的解决方案是使用升级信号。例如,当您收到
SIGQUIT
或SIGINT
时,您可以设置标志或以其他方式告诉线程是时候清理并退出进程了 - 否则< /强>。然后,假设五秒钟后,无论关闭您的进程的是什么,都会发送SIGTERM
并且“否则”就会发生。当您收到SIGTERM
时,您的信号处理程序只需调用_exit()
- 这些线程有机会,但他们搞砸了,这是他们的错。或者,您可以调用abort()
来生成核心文件,并可能提供足够的证据来修复不会关闭的恶意线程。最后,五秒钟后,管理进程将使用
SIGKILL
将该进程从轨道上删除,以确保确定。How is that defined? Because there's no way to "exit quickly as possible" when you receive one signal like that.
You can either set flag(s), post to semaphore(s), or similar to set a state that tells other threads it's time to shut down, or you can kill the entire process.
If you elect to set flag(s) or similar to tell the other threads to shut down, you set those flags and return from your signal handler and hope the threads behave and the process shuts down cleanly.
If you elect to kill threads, there's effectively no difference in killing a thread, killing the process, or calling
_exit()
. You might as well just keep it simple and call_exit()
.That's all you can chose between when you have to make your decision in a single signal handler call. Pick one.
A better solution is to use escalating signals. For example, when you get
SIGQUIT
orSIGINT
, you set flag(s) or otherwise tell threads it's time to clean up and exit the process - or else. Then, say five seconds later whatever is shutting down your process sendsSIGTERM
and the "or else" happens. When you getSIGTERM
, your signal handler simply calls_exit()
- those threads had their chance and they messed it up and that's their fault. Or you can callabort()
to generate a core file and maybe provide enough evidence to fix the miscreant threads that won't shut down.And finally, five seconds later the managing process will nuke the process from orbit with
SIGKILL
just to be sure.