Отмена потока с помощью pthread_cancel: хорошая практика или плохая - PullRequest
25 голосов
/ 21 января 2011

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

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

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

Ответы [ 4 ]

43 голосов
/ 21 января 2011

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

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

10 голосов
/ 21 января 2011

Если вы пишете код C ++, безопасный для исключений (см. http://www.boost.org/community/exception_safety.html), то ваш код, естественно, готов к отмене потока. glibs создает исключение C ++ при отмене потока , чтобы ваши деструкторы могли выполнить соответствующая очистка.

0 голосов
/ 31 декабря 2016

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

#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 );
}
0 голосов
/ 06 июня 2016

Я бы использовал 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 - замечательный инструмент.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...