I have a simple test of cancellation of a pthread when assigning this function as a work function:
static void * thread_start(void *arg)
{
printf("New thread started\n");
pthread_cleanup_push(cleanup_handler, NULL);
pthread_cancel(pthread_self());
pthread_testcancel(); /* A cancellation point */
return NULL;
}
The cleanup_handler:
static void cleanup_handler(void *arg)
{
printf("Called clean-up handler\n");
}
But I get compiler error of some irrelevant syntax error (missing '}' somewhere else). On the other hand, if I add pthread_cleanup_pop(1) like this:
static void * thread_start(void *arg)
{
printf("New thread started\n");
pthread_cleanup_push(cleanup_handler, NULL);
pthread_cancel(pthread_self());
pthread_testcancel(); /* A cancellation point */
pthread_cleanup_pop(1); //added this
return NULL;
}
it compiles and run as expected (pthread_cleanup_pop(1) is not run). The cleanup_handler is executed and thread returns PTHREAD_CANCLED.
It is completely irrelevant to have pthread_cleanup_pop(1) in the end, since all cleanup handlers should always run when a thread is about to be terminated. I don't even care if they are run without my cancellation.
What is wrong?
Looking at the man
POSIX.1 permits pthread_cleanup_push() and pthread_cleanup_pop() to be implemented as macros that expand to text containing '{' and '}', respectively. For this reason, the caller must ensure that calls to these functions are paired within the same function, and at the same lexical nesting level. (In other words, a clean-up handler is established only during the execution of a specified section of code.)
Emphasis mine