Подтвердить что ты не робот

Отмена потока с помощью pthread_cancel: хорошая практика или плохая

У меня есть программа на С++ в Linux (CentOS 5.3), создающая несколько потоков, которые находятся в бесконечном цикле для выполнения задания и сна в течение определенных минут. Теперь мне нужно отменить текущие потоки, если появится новое уведомление о конфигурации и только что начал новый набор потоков, для которых я использовал pthread_cancel. То, что я наблюдал, нити не прекращались даже после получения подтверждения отмены, даже некоторые спальные нити поднимались после того, как сон был завершен.

Поскольку поведение не было желательным, использование pthread_cancel в упомянутом сценарии ставит вопрос о хорошей или плохой практике.

Прокомментируйте использование pthread_cancel в вышеупомянутом сценарии.

4b9b3361

Ответ 1

В целом сокращение потока не очень хорошая идея. Лучше, когда это возможно, иметь общий флаг, который используется потоками для выхода из цикла. Таким образом, вы дадите потокам выполнить какую-либо очистку, которую им может понадобиться, прежде чем выходить.

В связи с тем, что потоки фактически не отменены, спецификация POSIX определяет набор точек отмены (man 7 pthreads). Темы могут быть отменены только в этих точках. Если ваш бесконечный цикл не содержит точку отмены, вы можете добавить ее, вызвав pthread_testcancel. Если pthread_cancel был вызван, то на этом этапе будет действовать.

Ответ 3

Я бы использовал boost:: asio.

Что-то вроде:

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

Как только у вас есть голова вокруг него, asio - прекрасный инструмент.

Ответ 4

Вы можете сделать эквивалент кода ниже.

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