开发者

Change pthread cancel type of another thread?

开发者 https://www.devze.com 2023-03-18 10:36 出处:网络
What I want to accomplish is that a main thread tries a normal deferred cancel first on a worker thread (executing code that is for my purposes a black box), and then if the thread is 开发者_Python百科

What I want to accomplish is that a main thread tries a normal deferred cancel first on a worker thread (executing code that is for my purposes a black box), and then if the thread is 开发者_Python百科still running after a timeout (pthread_timedjoin_np()), I want to do an asynchronous cancel. The problem I'm having is that pthread_setcanceltype() is only for the calling thread. Is there some workaround or hack that will let me do this? I want to avoid using signals as at least under Linux it seems that an asynchronous cancel will still execute C++ destructors of the thread's objects, which is important for me.


There are some cases, when pthread_setcanceltype() must actually do a cancel (see source below). So, this is a reason, why there is no pthread_setcanceltype_for_thread(). The actual cancel type is the field in pthread struct, which must be changed atomically.

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)

If you have a big need to change canceltype externally, you can hack the library and set the field directly.

PS: for NPTL (current implementation of pthreads in glibc on Linux) the easiest way to see how to get struct pthread from int pthread_t is ... pthread_join:

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

精彩评论

暂无评论...
验证码 换一张
取 消