linux thread cancellation of termination method

  • 2020-05-15 03:24:12
  • OfStack

Key:

The pthread_cancel function sends a termination signal
The pthread_setcancelstate function sets how to terminate
pthread_testcancel function cancels thread (another function is: setting the cancel point)

1 thread undefined

In general, a thread will automatically terminate when its main function exits, but it can also be forced to terminate when it receives a termination (cancellation) request from another thread.

Semantics of thread cancellation

The thread cancels by sending an Cancel signal (pthread_cancel function sends an Cancel signal) to the target thread, but it is up to the target thread to decide what to do with the Cancel signal, either to ignore it, or to terminate it immediately, or to continue running to Cancelation-point (cancellation point), depending on the Cancelation state (pthread_setcancelstate function setting state).

The default processing of the thread receiving the CANCEL signal (that is, the default state of the pthread_create() creation thread) is to continue to run to the cancellation point, that is, to set an CANCELED state, the thread continues to run, and only exits when it runs to Cancelation-point.

3 cancel point

According to the POSIX standard, pthread_join(), pthread_testcancel(), pthread_cond_wait(), pthread_cond_timedwait(), sem_wait(), sigwait() and other system calls that cause blocking are Cancelation-point, while other pthread functions do not cause Cancelation actions. However, the man page of pthread_cancel claims that none of the functions of C library are Cancelation-point at present due to the poor integration of LinuxThread library and C library. However, the CANCEL signal causes the thread to exit from the blocked system call and concatenate the EINTR error code, so you can call pthread_testcancel() before and after the system call that needs to be Cancelation-point to achieve the goal required by the POSIX standard, which is the following code snippet:

pthread_testcancel();
retcode = read(fd, buffer, length);
pthread_testcancel();

4. Programming considerations

If a thread is in an infinite loop and there is no inevitable path to the cancellation point within the loop body, the thread cannot be terminated by a cancellation request from an external thread. Therefore, a call to pthread_testcancel() should be added to the path that such a loop body must take.

5 the pthread function associated with thread cancellation

int pthread_cancel(pthread_t thread)

Sends a termination signal to the thread thread and returns 0 on success, otherwise a non-0 value. A successful delivery does not mean that the thread will terminate.

int pthread_setcancelstate(int state, int *oldstate)

Set the thread's response to Cancel signal. state has two values: PTHREAD_CANCEL_ENABLE (default) and PTHREAD_CANCEL_DISABLE. If old_state is not NULL, the original Cancel state is saved for recovery.

int pthread_setcanceltype(int type, int *oldtype)

type has two values: PTHREAD_CANCEL_DEFFERED and PTHREAD_CANCEL_ASYCHRONOUS. Cancel is only valid when the state of Cancel is Enable. It means to continue to run to the next cancellation point after receiving the signal and then exit, and to execute the cancellation action immediately (exit). If oldtype is not NULL, the shipped cancel action type value is stored.

void pthread_testcancel(void)

Function 1: set the cancel point;

Function 2: check whether this thread is in the state of Canceld, if so, cancel action, otherwise directly return.

Code:


#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>


#define THREAD_MAX 4


pthread_mutex_t mutex;
pthread_t thread[THREAD_MAX];


static int tries;
static int started;


void print_it(int *arg)
{
pthread_t tid;
tid = pthread_self();
printf("Thread %lx was canceled on its %d try.\n",tid,*arg);
}


void *Search_Num(int arg)
{
pthread_t tid;
int num;
int k=0,h=0,j;
int ntries;
tid = pthread_self();

/*while(pthread_mutex_trylock(&mutex) == EBUSY)
{
printf("**************busy****************\n");
pthread_testcancel();
}*/
srand(arg);
num = rand()&0xFFFFFF;
//pthread_mutex_unlock(&mutex);

printf("thread num %lx\n",tid);

ntries = 0;
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,NULL);

pthread_cleanup_push((void *)print_it,(void *)&ntries);

while(1)
{
num = (num+1)&0xffffff;
ntries++;

if(arg == num)
{
// Only allow 1 Three threads operate here 
while(pthread_mutex_trylock(&mutex) == EBUSY) { 
//1 After three threads operate, the remaining threads enter the next loop to suspend and wait pthread_cancel Function to send cancel Signal termination thread 
k++;
if(k == 10000)
{
printf("----------2busy2-----------\n");
}

pthread_testcancel();
}
tries = ntries;
//pthread_mutex_unlock(&mutex);  // If you add this, several threads will find the value set in the main function pid
printf("Thread %lx found the number!\n",tid);

for(j = 0;j<THREAD_MAX;j++)
{
if(thread[j]!=tid)
{
pthread_cancel(thread[j]);
}
}

break;
}
if(ntries%100 == 0)
{
h++;
/* Thread blocks, other threads scramble for resources, or wait pthread_cancel Function to send cancel Signal termination thread */
pthread_testcancel();
/* This is just to make sense of it pthread_testcancel The function sets the snippet of code */
if(h == 10000)
{
h = 0;
printf("----------thread num %lx-------------\n",tid);
}
}
}
pthread_cleanup_pop(0);
return (void *)0;
}


int main()
{
int i,pid;

pid = getpid(); // Sets the number to look for 

pthread_mutex_init(&mutex,NULL);
printf("Search the num of %d\n",pid);
for(started = 0; started < THREAD_MAX; started++)
{
pthread_create(&thread[started],NULL,(void *)Search_Num,(void *)pid);
}

for(i = 0; i < THREAD_MAX; i++)
{
printf("-----------i = %d--------------\n",i);
pthread_join(thread[i],NULL);
}
printf("It took %d tries ot find the number!\n",tries);
return 0;
}

Operation results:


Search the num of 6531
-----------i = 0--------------
thread num b6fbcb70
thread num b67bbb70
thread num b5fbab70
thread num b77bdb70
----------thread num b67bbb70-------------
Thread b67bbb70 found the number!
----------thread num b6fbcb70-------------
----------thread num b77bdb70-------------
----------2busy2-----------
----------thread num b5fbab70-------------
----------2busy2-----------
Thread b5fbab70 was canceled on its 1174527 try.
Thread b77bdb70 was canceled on its 1023100 try.
-----------i = 1--------------
Thread b6fbcb70 was canceled on its 1174527 try.
-----------i = 2--------------
-----------i = 3--------------
It took 1174527 tries ot find the number!

Do you see anything in the results? Ha ha ~ ~


Related articles: