Безопасно ли вызывать pthread_cancel () в завершенном потоке? - PullRequest
11 голосов
/ 30 августа 2011

Мне интересно, безопасно ли вызывать pthread_cancel() в завершенном потоке.Я не смог найти никаких подсказок на странице руководства.Заранее спасибо за любые подсказки.

Редактировать: Возможно, я не был достаточно точным.Я не говорю о потоках, завершенных более ранней функцией pthread_cancel (), но о потоках, которые просто вернулись из своей функции потока.

Ответы [ 3 ]

11 голосов
/ 30 августа 2011

Я думаю, что необходимо для безопасности, или pthread_cancel будет проблематично (рядом с непригодным для использования).

Действительно, если бы это было небезопасно, каждый вызов pthread_cancel должен был бы быть чрезвычайно сложным, проверяя, жив ли поток (и гарантировал, что он остается живым, пока вы не отмените его). Простое «ты все еще там» не подойдет.

В заключение я считаю, что pthread_cancel должен быть безопасным, если поток завершен. Конечно, это может быть не так для завершенного и присоединенного потока.

7 голосов
/ 30 августа 2011

На самом деле есть подсказка:

ОШИБКИ top

  ESRCH  No thread with the ID thread could be found.

А МКС дает немного другое описание:

ESRCH

поток не указывает текущий запущенный поток в процессе.

OpenGroup рекомендует:

Если реализация обнаруживает использование идентификатора потока после окончания срока его службы, рекомендуется, чтобы функция завершилась сбоем и сообщила об ошибке [ESRCH].

UPDATE

в NPTL есть проверка для двойной отмены или отмены после выхода:

  /* We are canceled now.  When canceled by another thread this flag
     is already set but if the signal is directly send (internally or
     from another process) is has to be done here.  */
  int newval = oldval | CANCELING_BITMASK | CANCELED_BITMASK;

  if (oldval == newval || (oldval & EXITING_BITMASK) != 0)
    /* Already canceled or exiting.  */
    break;

Итак, вторая отмена или отмена после выхода будет noop для мертвой нити.

Exiting_bitmask устанавливается __ do_cancel:

/* Called when a thread reacts on a cancellation request.  */
static inline void
__attribute ((noreturn, always_inline))
__do_cancel (void)
{
  struct pthread *self = THREAD_SELF;

  /* Make sure we get no more cancellations.  */
  THREAD_ATOMIC_BIT_SET (self, cancelhandling, EXITING_BIT);

__ do_cancel является реакцией на асинхронную отмену и на pthread_exit

void
__pthread_exit (value)
     void *value;
{
  THREAD_SETMEM (THREAD_SELF, result, value);

  __do_cancel ();
4 голосов
/ 02 мая 2012

Нет, не безопасно вызывать pthread_cancel () для потока, который был прерван.

Причина в том, что реализация может повторно использовать идентификатор потока завершенного потока для другого потока, и вызов "pthread_cancel ()" для этого TID может инициировать завершение в потоках, которое не должно быть завершено, или неопределенное поведение.

...