Изменить pthread отменить тип другого потока? - PullRequest
1 голос
/ 06 июля 2011

Что я хочу сделать, так это чтобы основной поток пытался выполнить обычную отложенную отмену сначала в рабочем потоке (выполнение кода, который для моих целей является черным ящиком), а затем, если поток все еще работает после истечения времени ожидания (pthread_timedjoin_np()), Я хочу сделать асинхронную отмену.У меня проблема в том, что pthread_setcanceltype() только для вызывающего потока.Есть ли обходной путь или хак, который позволит мне сделать это?Я хочу избегать использования сигналов, поскольку, по крайней мере, в Linux кажется, что асинхронная отмена все равно будет выполнять деструкторы C ++ объектов потока, что важно для меня.

1 Ответ

2 голосов
/ 06 июля 2011

В некоторых случаях pthread_setcanceltype() действительно должен сделать отмену (см. Источник ниже). Итак, это причина, почему нет pthread_setcanceltype_for_thread(). Фактический тип отмены - это поле в структуре pthread, которое должно быть изменено атомарно.

FTP: //sources.redhat.com/pub/glibc/snapshots/glibc-latest.tar.bz2/glibc-20090518/nptl/pthread_setcanceltype.c

__pthread_setcanceltype (type, oldtype)
     int type;
     int *oldtype;
{
  volatile struct pthread *self;

  self = THREAD_SELF;

  int oldval = THREAD_GETMEM (self, cancelhandling);
  while (1)
    {
      int newval = (type == PTHREAD_CANCEL_ASYNCHRONOUS
                    ? oldval | CANCELTYPE_BITMASK
                    : oldval & ~CANCELTYPE_BITMASK);

      /* Store the old value.  */
      if (oldtype != NULL)
        *oldtype = ((oldval & CANCELTYPE_BITMASK)
                    ? PTHREAD_CANCEL_ASYNCHRONOUS : PTHREAD_CANCEL_DEFERRED);

      /* Update the cancel handling word.  This has to be done
         atomically since other bits could be modified as well.  */
      int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval,
                                              oldval);
      if (__builtin_expect (curval == oldval, 1))
        {
          if (CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS (newval))
            {
              THREAD_SETMEM (self, result, PTHREAD_CANCELED);
              __do_cancel ();  // HERE THE CANCELLING
            }

          break;
        }

      /* Prepare for the next round.  */
      oldval = curval;
    }

  return 0;
}
strong_alias (__pthread_setcanceltype, pthread_setcanceltype)

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

PS: для NPTL (текущая реализация pthreads в glibc в Linux) Самый простой способ узнать, как получить struct pthread из int pthread_t - это ... pthread_join:

 pthread_join (pthread_t threadid, thread_return) 
 { 
     struct pthread *pd = (struct pthread *) threadid;
...