Program:
// C program to demonstrates cancellation of self thread
// using thread id
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h> // For memset
static pthread_mutex_t cfglock = PTHREAD_MUTEX_INITIALIZER;
int is_thread_cancel = 0, is_cleanup_push = 0;
void line_80(char ch)
{
char str[81] = {'\0'};
memset(str, ch, sizeof(str));
str[80] = '\0';
printf("%s\n", str);
return;
}
void *calls(void* ptr)
{
int oldtype = 0;
printf("\nThread: Entrying into the thread %s \n", __func__);
line_80('-');
/* If 2 argument try then do the clean up */
/* Add setcanceltype & cleanup into the if loop throws below error:
error: expected ‘while’ before ‘printf’
Reason is pthread_cleanup_push is not a function, it is a macro it cotain the below.
So it add the d0 { on start and pthread_cleanup_pop macro contain ending while, so we could not put inside the if condition
if (is_cleanup_push) {
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype);
do { __pthread_unwind_buf_t __cancel_buf; void (*__cancel_routine) (void *) = (pthread_mutex_unlock); void *__cancel_arg = ((void *) &cfglock); int __not_first_call = __sigsetjmp ((struct __jmp_buf_tag *) (void *) __cancel_buf.__cancel_jmp_buf, 0); if (__builtin_expect ((__not_first_call), 0)) { __cancel_routine (__cancel_arg); __pthread_unwind_next (&__cancel_buf); } __pthread_register_cancel (&__cancel_buf); do {;
}
pthread_cleanup_pop macro definition is:
do { } while (0); } while (0); __pthread_unregister_cancel (&__cancel_buf); if (0) __cancel_routine (__cancel_arg); } while (0);
pthread_setcanceltype(oldtype, ((void *)0));
*/
// if (is_cleanup_push) {
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype);
pthread_cleanup_push(pthread_mutex_unlock, (void *) &cfglock);
// }
printf("Thread: Going to accquire the lock\n");
pthread_mutex_lock(&cfglock);
printf("Thread: Lock is accquired \n");
printf("Thread: Going to sleep 10 second \n");
sleep(7);
printf("Thread: After the sleep of 10 second\n");
/* If 2 argument try then do the clean up */
// if (is_cleanup_push) {
pthread_mutex_unlock(&cfglock);
pthread_cleanup_pop(0);
pthread_setcanceltype(oldtype, NULL);
//}
printf("\nThread: Returning from thread %s \n", __func__);
line_80('-');
return NULL;
}
int main(int argc, char *argv[])
{
// NULL when no attribute
pthread_t thread = 0;
int ret = 0;
void *thread_ret = NULL;
// calls is a function name
pthread_create(&thread, NULL, calls, NULL);
/* Argument and his valuel
Arg 1. if 0 then no cancel, if 1 then it will call pthread_cancel.
Scenario: if 0 then, no cancel, thread in lock, process also try to lock, Dead lock
scenario 2: if 1 then , cancel kill the thread but lock is not cleaned, so proacess try to lock, hence Dead lock.
Arg 2. if 0 then no cleanup_push for lock,
if 1 then do cleanup_push for lock
*/
printf("Process: going to sleep for 3 \n");
sleep(3);
printf("\t\tProcess: After sleep of 3 second \n");
is_thread_cancel = atoi(argv[1]);
is_cleanup_push = atoi(argv[2]);
if (is_thread_cancel == 1) {
/* cancelled threads do not unlock mutexes they hold */
printf("Process: called the pthread_cancel \n");
ret = pthread_cancel(thread);
if (ret == 0) {
printf("Process: Canceled the thread with ID <%ld> \n", thread);
} else {
printf("Process: Error in cancel while try to cancel the thread <%ld>, ret = %d \n",
thread, ret);
}
}
// printf("After cancel \n");
/* Already taken the lock in thread, so this lock will be blocked */
printf("Process: Going to acquire the Mutux \n");
pthread_mutex_lock(&cfglock);
printf("\t\tProcess: Lock is acquired \n");
pthread_mutex_unlock(&cfglock);
printf("\t\tProcess: Mutux lock is released \n");
printf("Process: going to sleep for 15 \n");
sleep(10);
printf("\t\tProcess: After sleep of 15 second \n");
/* The pthread_join() function waits for the thread specified by thread to terminate.
* If that thread has already terminated, then pthread_join() returns immediately.
* If the target thread was canceled, then PTHREAD_CANCELED is placed in *retval.
* As per out PTHREAD_CANCELED value is 0xfffff
*/
// Waiting for when thread is completed
// ret = pthread_join(thread, NULL); // Just wati
ret = pthread_join(thread, &thread_ret); // Just wati
if (ret !=0) {
printf("Process: Error in pthread_join errno = %d \n", ret);
}
printf("Process: The return value from thread is = %p \n", thread_ret);
if (thread_ret == PTHREAD_CANCELED) {
printf("Process: The thread is already canceled, value of PTHREAD_CANCELED <%p>\n", PTHREAD_CANCELED);
}
return 0;
}
/* Ref:
For Dedlock release lock, Solution:
https://stackoverflow.com/questions/14268080/cancelling-a-thread-that-has-a-mutex-locked-does-not-unlock-the-mutex
Solution method 2: For pthread_mutexattr_setrobust to releace lock:
http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutexattr_setrobust.html
https://en.wikipedia.org/wiki/Resource_acquisition_is_initialization
Solution Method 1:
https://sector7.xray.aps.anl.gov/~dohnarms/programming/glibc/html/Cleanup-Handlers.html
https://linux.die.net/man/3/pthread_cleanup_push
*/
No comments:
Post a Comment