if (ret < 0)
return ret;
+ /* Threads can be cancelled before they give up a lock.
+ * Therefore cancellation is temporarily disabled.
+ * This solution is comparatively simple and cheap.
+ * The other solutions (cleanup handlers, robust mutexes)
+ * would be much more complicated and also inflict larger
+ * runtime costs. The downside of disabling cancellation
+ * is not a problem in our case because it is temporary
+ * and very brief so we don't keep an obsolete thread
+ * for much longer than we otherwise would. */
+ int old_cancel_state;
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_cancel_state);
+
/* The only thing that needs to be protected here is `write_to_log` since
* all other resources already have their own specific locks (and even the
* pointer could be made to point at a null handler instead of a true NULL)
;
pthread_rwlock_unlock(&log_destruction_lock);
} else
- return DLOG_ERROR_NOT_PERMITTED;
+ ret = DLOG_ERROR_NOT_PERMITTED;
+
+ pthread_setcancelstate(old_cancel_state, NULL);
return ret;
}