Question

I am maintaining some code right now, that creates a pthread with pthread_create(). This thread also calls pthread_detach(pthread_self()); soon after creation. Furthermore it uses pthread_cleanup_push() to push a clean-up handler. The only cancellation point of this thread is a call to pthread_testcancel() at the end of the threads main loop.

I now see, that at some point pthread_cancel() gets called on this thread and (almost) always returns a nonzero value. Checking errno results in EINPROGRESS. What exactly does this mean? Because the man pages states

On success, pthread_cancel() returns 0

However, it also mentions,

that cancellation will be delayed until the thread next calls a function that is a cancellation point.

So if a return value of nonzero and errno equal to EINPROGRESS means, that the cancellation request got queued, but was not yet reacted upon, I would expect that to be always the case. But if a return value of 0 indicates success, then it must mean something different.

What does EINPROGRESS mean in this circumstance and how can I make sure, that the thread got canceled correctly or was already terminated?


I am running Debian 7.4 with libpthread-2.13 as part of libc6:amd64 2.13-38+deb7u1 in a VM.

Was it helpful?

Solution

I now see, that at some point pthread_cancel() gets called on this thread and (almost) always returns a nonzero value. Checking errno results in EINPROGRESS.

The pthread* family of functions does not set errno, but instead returns the error code as function value.

So do not only test the outcome of the call to pthread_cancel() against 0, but actually interpret the value returned as what you "normaly" find in errno, that is one of the E* error values.

int result = pthread_cancel(<some-pthread>);
if (0 != result)
{
  fprintf(stderr, "pthread_cancel() failed with error #%d: '%s'\n", result, strerror(result)); /* Better use strerror_r() in a multithreaded enviroment. */
}

Btw: Inspecting the sources of the libc you seem to be using does not reveal any hints of pthread_cancel() returning EINPROGRESS.

OTHER TIPS

A thread's cancelability state, determined by pthread_setcancelstate(3), can be enabled (the default for new threads) or disabled. If a thread has disabled cancellation, then a cancellation request remains queued until the thread enables cancellation. If a thread has enabled cancellation, then its cancelability type determines when cancellation occurs.

-

A thread's cancellation type, determined by pthread_setcanceltype(3), may be either asynchronous or deferred (the default for new threads). Asynchronous cancelability means that the thread can be canceled at any time (usually immediately, but the system does not guarantee this). Deferred cancelability means that cancellation will be delayed until the thread next calls a function that is a cancellation point.

EINPROGRESS:

An operation that cannot complete immediately was initiated on an object that has non-blocking mode selected. Some functions that must always block (such as connect) never return EAGAIN; instead, they return EINPROGRESS to indicate that the operation has begun and will take some time. Attempts to manipulate the object before the call completes return EALREADY.

...how can I make sure, that the thread got canceled correctly 
or was already terminated?

You can use the select function to find out when the pending operation has completed.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top