Is it safe to call pthread_cancel() on terminated thread?

前端 未结 4 861
误落风尘
误落风尘 2021-02-08 00:45

I\'m wondering if it is safe to call pthread_cancel() on a terminated thread. I couldn\'t find any hints in the manual page. Thanks in advance for any hints.

<
相关标签:
4条回答
  • 2021-02-08 00:47

    There is a hint actually:

    ERRORS top

      ESRCH  No thread with the ID thread could be found.
    

    And MKS gives a bit other description:

    ESRCH

    thread does not specify a currently running thread in the process.

    OpenGroup recommends:

    If an implementation detects use of a thread ID after the end of its lifetime, it is recommended that the function should fail and report an [ESRCH] error.

    UPDATE

    in NPTL there is a check for double cancel or cancel after exit:

      /* 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;
    

    So, second cancel or cancel after exit will be a noop for dead thread.

    The exiting_bitmask is set by __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 is both reaction to async cancel and to pthread_exit

    void
    __pthread_exit (value)
         void *value;
    {
      THREAD_SETMEM (THREAD_SELF, result, value);
    
      __do_cancel ();
    
    0 讨论(0)
  • 2021-02-08 00:57

    No, it isn't safe to call pthread_cancel() on a thread that has been terminated.

    The reason is that the implementation may reuse the thread ID of the terminated thread for another thread and calling "pthread_cancel()" on that TID may trigger the termination on threads that shouldn't be terminated or undefined behaviour.

    0 讨论(0)
  • 2021-02-08 00:59

    Yes, it is safe to call it before pthread_detach or pthread_join has been called. However, according to my experiments, it can return ESRCH (=3) if the thread has already returned from its thread function. (gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0)

    #include "gtest/gtest.h"
    
    static void *S_ThreadEntry1(void* pvarg)
    {
         return 0;
    }
    
    TEST(ThreadTest, PthreadCancelAfterExit)
    {
         pthread_t threadid;
         ASSERT_EQ(pthread_create(&threadid, 0, &S_ThreadEntry1, nullptr), 0);
         sleep(1);
    
         int cancel_ret = pthread_cancel(threadid);
         std::cout << "pthread_cancel returned " << cancel_ret << std::endl;
         if (cancel_ret != 0)
              EXPECT_EQ(cancel_ret, ESRCH);
         void* res;
         EXPECT_EQ(pthread_join(threadid, &res), 0);
         std::cout << "res=" << res << std::endl;
    }
    

    Output:

    [ RUN      ] ThreadTest.PthreadCancelAfterExit
    pthread_cancel returned 3
    res=0
    [       OK ] ThreadTest.PthreadCancelAfterExit (1000 ms)
    
    0 讨论(0)
  • 2021-02-08 01:07

    I think it needs to be safe, or pthread_cancel would be problematic (next to unusable).

    Indeed, if it wouldn't be safe, every call to pthread_cancel would have to be enormously complicated by checking the thread is alive (and ensuring it stays alive until you get to cancel it). A simple "are you still there" wouldn't do.

    In conclusion, I believe pthread_cancel must be safe if the thread has terminated. Of course, this might not be the case for a terminated and joined thread.

    0 讨论(0)
提交回复
热议问题