简体   繁体   English

使用pthread_cancel取消线程:良好做法或不好

[英]Cancelling a thread using pthread_cancel : good practice or bad

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. 我在Linux(CentOS 5.3)上有一个C ++程序,它产生多个线程,这些线程处于无限循环中以执行作业并在某些时间内休眠。 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. 现在我必须取消正在运行的线程以防新的配置通知进入并重新启动新的线程集,我已经使用了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. 我观察到的是,即使在接收到取消指示后,线程也没有停止,甚至在睡眠完成后一些睡眠线程也会出现。

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用法。

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 ). 在没有实际取消的线程问题上,POSIX规范确定了一组取消点( 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 . 如果您的无限循环不包含取消点,您可以通过调用pthread_testcancel添加一个取消点。 If pthread_cancel has been called, then it will be acted upon at this point. 如果已调用pthread_cancel ,则此时将对其执行操作。

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. 如果您正在编写异常安全的C ++代码(请参阅http://www.boost.org/community/exception_safety.html ),那么您的代码自然可以用于线程取消。 glibs throws C++ exception on thread cancel , so that your destructors can do the appropriate clean-up. glibs在线程取消时引发C ++异常 ,因此你的析构函数可以进行适当的清理。

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就是一个很棒的工具。

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 );
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM