Linux 使用 pthread_cancel 取消线程:好的做法或不好的做法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4760687/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Cancelling a thread using pthread_cancel : good practice or bad
提问by Mandar
I have a C++ program on Linux (CentOS 5.3) spawning multiple threads which are in an infinite loop to perform a job and sleep for certain minutes. Now I have to cancel the running threads in case a new configuration notification comes in and freshly start new set of threads, for which i have used pthread_cancel. What I observed was, the threads were not getting stopped even after receiving cancel indication,even some sleeping threads were coming up after the sleep was completed.
我在 Linux (CentOS 5.3) 上有一个 C++ 程序,它产生多个线程,这些线程处于无限循环中以执行作业并休眠特定分钟。现在我必须取消正在运行的线程,以防出现新的配置通知,并重新启动新的线程集,为此我使用了 pthread_cancel。我观察到的是,即使在收到取消指示后线程也没有停止,甚至在睡眠完成后也出现了一些睡眠线程。
As the behavior was not desired, usage of pthread_cancel in the mentioned scenario raises question about being good or bad practice.
由于不希望出现这种行为,因此在上述场景中使用 pthread_cancel 会引发关于实践是好是坏的问题。
Please comment on the pthread_cancel usage in above mentioned scenario.
请评论上述场景中的 pthread_cancel 用法。
采纳答案by David Rodríguez - dribeas
In general thread cancellation is not a really good idea. It is better, whenever possible, to have a shared flag, that is used by the threads to break out of the loop. That way, you will let the threads perform any cleanup they might need to do before actually exiting.
一般来说,取消线程并不是一个好主意。只要有可能,最好有一个共享标志,线程使用它来跳出循环。这样,您将让线程在实际退出之前执行它们可能需要执行的任何清理。
On the issue of the threads not actually cancelling, the POSIX specification determines a set of cancellation points ( man 7 pthreads). Threads can be cancelled only at those points. If your infinite loop does not contain a cancellation point you can add one by calling pthread_testcancel
. If pthread_cancel
has been called, then it will be acted upon at this point.
关于线程实际上没有取消的问题,POSIX 规范确定了一组取消点(man 7 pthreads)。线程只能在这些点被取消。如果您的无限循环不包含取消点,您可以通过调用添加一个取消点pthread_testcancel
。如果pthread_cancel
已被调用,则此时将对其执行操作。
回答by Maxim Egorushkin
If you are writing exception safe C++ code (see http://www.boost.org/community/exception_safety.html) than your code is naturally ready for thread cancellation. glibs throws C++ exception on thread cancel, so that your destructors can do the appropriate clean-up.
如果您正在编写异常安全的 C++ 代码(请参阅http://www.boost.org/community/exception_safety.html),那么您的代码自然已准备好进行线程取消。glibs 在线程 cancel 上抛出 C++ 异常,以便您的析构函数可以进行适当的清理。
回答by Nicole
I'd use boost::asio.
我会使用 boost::asio。
Something like:
就像是:
struct Wait {
Wait() : timer_(io_service_), run_(true) {}
boost::asio::io_service io_service_;
mutable boost::asio::deadline_timer timer_;
bool run_;
};
void Wait::doWwork() {
while (run) {
boost::system::error_code ec;
timer_.wait(ec);
io_service_.run();
if (ec) {
if (ec == boost::asio::error::operation_aborted) {
// cleanup
} else {
// Something else, possibly nasty, happened
}
}
}
}
void Wait::halt() {
run_ = false;
timer_.cancel();
}
Once you've got your head round it, asio is a wonderful tool.
一旦你了解了它,asio 就是一个很棒的工具。
回答by Hyman
You can do the equivalent of the code below.
您可以执行以下代码的等效操作。
#include <pthread.h>
#include <cxxabi.h>
#include <unistd.h>
...
void *Control(void* pparam)
{
try
{
// do your work here, maybe long loop
}
catch (abi::__forced_unwind&)
{ // handle pthread_cancel stack unwinding exception
throw;
}
catch (exception &ex)
{
throw ex;
}
}
int main()
{
pthread_t tid;
int rtn;
rtn = pthread_create( &tid, NULL, Control, NULL );
usleep(500);
// some other work here
rtn = pthtead_cancel( tid );
}