[POSIX thread] use of pthread_clean_push and pthread_clean_up

Source: Internet
Author: User

 

From: http://blog.chinaunix.net/u2/72995/showart_1218514.html void pthread_cleanup_push (void (* routine) (void *), void * Arg );
Void pthread_cleanup_pop (INT execute); // The Int parameter here. 0 indicates that push is not executed, but not 0 indicates execution.

The prototype is very simple, and the function is similar to atexit (), but one is thread and the other is process.
Used to set what to do when the push/pop thread exits.

Notes:
1. Push and pop must appear in pairs. In fact, push contains "{" and pop contains "}", but one less one does not work.
2. There can be multiple pushes, and the same pop should correspond to the number, following the "advanced post-release principle ".

The push function may be executed at the following three times:
1. The displayed call pthread_exit ();
Or
2. The cancel point thread is cancel.
Or
3. When the pthread_cleanup_pop () parameter is not 0.

The above actions are limited to the Code covered by push/pop.

The previous two are easy to understand. The key is the pthread_cleanup_pop parameter. In fact, Int Is because C does not have bool. The parameter here is only the difference between 0 and 0. For pthread_cleanup_pop, the values 5 and 10 are the same and both are non-0.

We often see this Code:
Void child (void * t)
{
Pthread_cleanup_push (pthread_mutex_unlock, & mutex );
Pthread_mutex_lock (& mutex );
..............
Pthread_mutex_unlock (& mutex );
Pthread_cleanup_pop (0 );
}

Why is pthread_cleanup_pop 0? He will not execute the function pointed to by the pointer of the function pushed in. Yes, it is not executed. It is troublesome to execute it.

Why do I have to write this sentence?

This is because push and pop must appear in pairs. If you do not write, it is a syntax error.

The purpose of this write is to ensure that mutex can be unlocked, because anything may happen between pthread_mutex_lock and pthread_mutex_unlock, for example, there are n cancel points, causing the thread to be given to cancel by the main or other threads, while the cancel action will not release the mutex lock, so the lock will be locked.

Use pthread_cleanup_push to add a function pthread_mutex_unlock. Refer to the execution time description above. When the thread is cancel, it can be used to release the lock. If the thread runs properly and knows that it is running to pthread_cleanup_pop, the lock has been released by pthread_mutex_unlock in the intermediate code. If the pthread_cleanup_pop parameter is not 0, it will be released again, the error is reported here and released twice.

Therefore, pthread_cleanup_pop (0) is required, because it must first appear in pairs. Secondly, we do not want it to be released twice.

Likewise:
Void * exit1 (void * t)
{
Printf ("exit1/N ");
}
Void * child (void * t)
{
Pthread_cleanup_push (exit1, null );
.....
Pthread_exit (null );
Pthread_cleanup_pop (0 );
}

The exit1 function is executed at pthread_exit (null). It does not matter if the pthread_cleanup_pop parameter is 0, because it cannot be executed here.

The change is as follows:
Pthread_cleanup_push (exit1, null );
......
Pthread_cleanup_pop (0 );
Pthread_exit (null );

Exit1 will not be executed because the pop parameter is 0. If you change the pop parameter to 1, exit1 will be executed. Will it be executed twice? No, because pthread_exit is outside the push/pop block, it will not trigger exit1.

Pthread_cleanup_push (exit1, null );
Pthread_cleanup_push (exit2, null );
........
Pthread_cleanup_pop (0 );
Pthread_cleanup_pop (1 );

Who respectively controls 0 and 1? Matching Principle: Unplug one pair from the outside to the inside. Obviously, 0 controls exit2.

A test procedure is attached:

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

void clean ( void * p )
{
        printf ( "clean()/n" );
}

void * thread ( void * p )
{

        pthread_cleanup_push( clean, NULL);
        printf ( "thread sleep/n" );
        sleep (10);
        printf("thread wake.../n");
        pthread_cleanup_pop(1);
}

int main ()
{
        pthread_t id;
        pthread_mutexattr_t attr;
        pthread_create ( &id, NULL, thread, NULL );
        printf ( "main sleep/n");
        sleep(3);
        printf ( "cancel thread:%u/n", id );
        pthread_cancel ( id );
        return 0;
}

/*
Output:
Thread sleep
Main sleep
Cancel thread: 1082399936
Clean ()
*/

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.