I have a problem with pthread cancellation and using cleanup handlers. In POSIX library there are two functions: pthread_cleanup_push and pthread_cleanup_pop. The problem is that they aren't functions but macros! Moreover it seems that they have to be placed in pairs i.e. for each push, there must be also pop. But I seems it is a little odd.
Suppose I have such code structure:
{
pthread_mutex_lock(&mutex);
pthread_cleanup_push(cleanup_mutex, &mutex);
// any code that can be cancellation point
while(/*some condition *) {
// any code that cancellation point
// 1. signaled -> thread given mutex
// 2. timeout -> thread given mutex
// 3. canceled -> thread given mutex and than cleanup handlers
if(pthread_cond_timedwait(&cond, &mutex, &abstimeout) == ETIMEDOUT) {
/*** HERE SHOULD BE pthread_cleanup_pop(0)! But it cannot be placed! case 2)***/
pthread_mutex_unlock(&mutex);
return NULL;
}
}
// any code that can be cancellation point
// consume something
// any code that can be cancellation point
pthread_cleanup_pop(0); // takes care of case 1)
pthread_mutex_unlock(&mutex);
return something;
}
Yeah, it's a little odd, but that's how it is. Worst case, you can use a goto
to jump to a return
statement in the appropriate scope. But there's usually a more natural way to do it.