Безопасно ли вызывать pthread_cancel() на завершенном потоке?

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

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

Ответ 1

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

В самом деле, если это не будет безопасно, каждый вызов pthread_cancel должен быть чрезвычайно сложным, если проверить, что поток жив (и обеспечить его сохранение до тех пор, пока вы не сможете его отменить). Простой "ты все еще там" не делал.

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

Ответ 2

Существует подсказка:

ОШИБКИ top

  ESRCH  No thread with the ID thread could be found.

И MKS дает немного другое описание:

ESRCH

В потоке

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

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

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

ОБНОВЛЕНИЕ

в 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 для мертвой нити.

Исходящая_битная маска устанавливается __ 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 ();

Ответ 3

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

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