We’ve been given some code to look at in preparation for an exam regarding pthreads and cancelling them properly. We’ve been asked to both explain what is wrong, and fix it.
My answer: The thread handler function enters a wait state without releasing the mutex, but I feel like I’m missing something. Here is the code, the lines adding a clean up handler were added to fix the program. Again, I’m not quite sure WHY this works. (I understand the concept of the clean up handler, but I don’t understand why it fixes this particular problem – another reason why I’m not sure that my answer is correct)
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cv = PTHREAD_COND_INITIALIZER;
const int flag = 1;
static void * cancelme(void *bb_in)
{
pthread_mutex_lock(&mutex);
/* Install a cleanup handler */
pthread_cleanup_push(pthread_mutex_unlock, &mutex);
while (flag) {
pthread_cond_wait(&cv, &mutex);
}
//before insertion of cleanup handlers: pthread_mutex_unlock(&mutex); was here
/* Uninstall cleanup handler */
pthread_cleanup_pop(1);
return (NULL);
}
int main()
{
pthread_t t;
pthread_create(&t, NULL, cancelme, NULL);
sleep(1);
pthread_cancel(t);
printf("Waiting for thread to finish...\n");
pthread_join(t, NULL);
printf("Thread finished...\n");
printf("Waiting to acquire lock...\n");
pthread_mutex_lock(&mutex);
printf("Lock acquired\n");
return (0);
}
Any feedback much appreciated.
It looks like the code to push the
pthread_mutex_unlockfunction onto the thread’s cleanup stack viapthread_cleanup_pushmakes the code snippet work because otherwise the thread would grab the shared lock and be forced to exit without releasing it.By pushing the
pthread_mutex_unlockfunction onto the cleanup stack, the thread is ensuring that the mutex will get unlocked when the thread exits, even if the exit is forced and thepthread_cleanup_popfunction is not hit.In essence the cleanup queue gives you the ability to ensure code gets executed / resources are freed / etc upon exit. The
pthread_cleanup_pop functionjust calls the top function on the cleanup stack, while exiting calls all the functions on the cleanup stack. See the man ofpthread_cleaup_pushfor more info.