1

我想要完成的是一个主线程首先在一个工作线程上尝试一个正常的延迟取消(执行我的目的是一个黑匣子的代码),然后如果线程在超时(pthread_timedjoin_np())后仍在运行,我想做一个异步取消。我遇到的问题pthread_setcanceltype()是只针对调用线程。是否有一些解决方法或黑客可以让我这样做?我想避免使用信号,因为至少在 Linux 下,异步取消似乎仍会执行线程对象的 C++ 析构函数,这对我来说很重要。

4

1 回答 1

2

在某些情况下,何时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)

如果您有很大的需要在外部更改 canceltype,您可以破解库并直接设置字段。

PS:对于 NPTL(Linux 上 glibc 中 pthreads 的当前实现),查看如何struct pthread从 int pthread_t 获取的最简单方法是... pthread_join:

 pthread_join (pthread_t threadid, thread_return) 
 { 
     struct pthread *pd = (struct pthread *) threadid;
于 2011-07-06T09:22:44.550 回答