PreviousNext

Cancellation Side Effects

Cancellation ordinarily involves cleanup in order to leave resources in an orderly state. Any side effects of acting upon a cancellation request occur before the first cleanup routine is called.

There are no side effects of acting upon a cancellation request while executing pthread_join( ).

The side effects of acting upon a cancellation request while in a condition variable wait are as follows:

· The mutex is reacquired before calling the first cleanup routine.

· In addition, while the thread is no longer considered to be waiting for the condition, no signals directed at the condition variable are consumed by the target thread if there are other threads blocked on the condition variable.

Using pthread_cancel( ) to Terminate a Thread

The pthread_cancel( ) routine allows a thread to cancel itself or another thread. The routine is fully described in the pthread_cancel(3thr) reference page. Its use is straightforward, but if you use it to cancel a thread that makes use of mutexes or condition variables, you should keep in mind the following aspect of its operation.

The canceled thread receives the cancel in the form of an exception. If the thread has not disabled its cancelability by a call to pthread_setcancel( ), its effect is to immediately terminate the thread. However, if the thread happens to have acquired a mutex (including the global lock) when it is canceled, the mutex will remain in its locked state and no other thread will be able to acquire it. Moreover, the data that was protected by the mutex may be in an inconsistent state as a result of the thread's having been canceled in the middle of its operation on the data.

The easiest way to prevent this is simply to disable cancels before entering code for which access has been restricted by a mutex. If this is undesirable, you can explicitly handle a cancel by coding an exception-handling block.

This same possibility exists with condition variables, since the variable is protected by a mutex. An example of handling a cancel (or any other exception) while using a condition variable follows.

#include <pthread_exc.h>

<...>

/* First, lock the mutex that protects the condition variable */
/* and the predicate... */
pthread_mutex_lock(some_object.mutex);

/* Add this thread to the total number of threads waiting for */
/* the condition... */
some_object.num_waiters = some_object.num_waiters + 1;

/* Enter the exception handling block... */
TRY

/* Test the predicate condition... */
while (! some_object.data_available)

/* If the desired condition is not yet true, wait for */
/* it to become true. This next call also auto- */
/* matically releases the mutex... */
pthread_cond_wait(some_object.condition, some_object.mutex);

/* Code to access data_available goes here */

<...>

/* If a "cancel" exception occurs during the call to */
/* pthread_cond_wait(), the thread will resume */
/* execution in the FINALLY block following... */
FINALLY

/* Remove this thread from the total number of threads */
/* waiting for the condition... */
some_object.num_waiters = some_object.num_waiters - 1;

/* Release the mutex, and then continue with the */
/* exception --that is, cancel ... */
pthread_mutex_unlock(some_object.mutex);
ENDTRY

Note that in order to handle the cancel as an exception, you must #include the pthread_exc.h header file rather than pthread.h; this allows you to use the DCE Threads exception interface.