Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between pthread_exit(PTHREAD_CANCELED) and pthread_cancel(pthread_self())

When pthread_exit(PTHREAD_CANCELED) is called I have expected behavior (stack unwinding, destructors calls) but the call to pthread_cancel(pthread_self()) just terminated the thread.

Why pthread_exit(PTHREAD_CANCELED) and pthread_cancel(pthread_self()) differ significantly and the thread memory is not released in the later case?

The background is as follows:

The calls are made from a signal handler and reasoning behind this strange approach is to cancel a thread waiting for the external library semop() to complete (looping around on EINTR I suppose)

I have noticed that calling pthread_cancel from other thread does not work (as if semop was not a cancellation point) but signalling the thread and then calling pthread_exit works but calls the destructor within a signal handler. pthread_cancel could postpone the action to the next cancellation point.

like image 734
aak Avatar asked Feb 20 '26 02:02

aak


1 Answers

In terms of thread specific clean-up behaviour there should be no difference between cancelling a thread via pthread_cancel() and exiting a thread via pthread_exit().

POSIX says:

[...] When the cancellation is acted on, the cancellation clean-up handlers for thread shall be called. When the last cancellation clean-up handler returns, the thread-specific data destructor functions shall be called for thread. When the last destructor function returns, thread shall be terminated.


From Linux's man pthread_cancel:

When a cancellation requested is acted on, the following steps occur for thread (in this order):

  1. Cancellation clean-up handlers are popped (in the reverse of the order in which they were pushed) and called. (See pthread_cleanup_push(3).)

  2. Thread-specific data destructors are called, in an unspecified order. (See pthread_key_create(3).)

  3. The thread is terminated. (See pthread_exit(3).)


Referring the strategy to introduce a cancellation point by signalling a thread, I have my doubts this were the cleanest way.

As many system calls return on receiving a signal while setting errno to EINTR, it would be easy to catch this case and simply let the thread end itself cleanly under this condition via pthread_exit().

Some pseudo code:

while (some condition) 
{
  if (-1 == semop(...))
  { /* getting here on error or signal reception */
    if (EINTR == errno)
    { /* getting here on signal reception */
      pthread_exit(...);
    }
  }
}
like image 167
alk Avatar answered Feb 22 '26 15:02

alk



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!