pthread_cleanup_push() — Establish a cleanup handler

Standards

Standards / Extensions C or C++ Dependencies

POSIX.4a
Single UNIX Specification, Version 3

both

POSIX(ON)

Format

#define _OPEN_THREADS
#include <pthread.h>

void pthread_cleanup_push(void (*routine)(void *arg), void *arg);

General description

Pushes the specified routine onto the calling thread's cleanup stack. The cleanup handler is executed as a result of a pthread_cleanup_pop(), with a nonzero value for the execute parameter.

When the thread ends, all pushed but not yet popped cleanup routines are popped from the cleanup stack and executed in last-in-first-out (LIFO) order. This occurs when the thread:
  • Calls pthread_exit()
  • Does a return from the start routine
  • Is canceled because of a pthread_cancel()

pthread_cleanup_push() and pthread_cleanup_pop() must appear in pairs and within the same lexical scope, or undefined behavior will result.

Special behavior for C++: Because C and C++ linkage conventions are incompatible, pthread_cleanup_push() cannot receive a C++ function pointer as the start routine function pointer If you attempt to pass a C++ function pointer to pthread_cleanup_push(), the compiler will flag it as an error. You can pass a C or C++ function to pthread_cleanup_push() by declaring it as extern "C".

Returned value

pthread_cleanup_push() returns no values.

This function is used as a statement.

If an error occurs while a pthread_cleanup_push() statement is being processed, a termination condition is raised.

There are no documented errno values. Use perror() or strerror() to determine the cause of an error.

Example

CELEBP16
⁄* CELEBP16 *⁄                                   
#define _OPEN_THREADS                                                           
                                                                                
#include <pthread.h>                                                            
#include <stdio.h>                                                              
#include <stdlib.h>                                                             
#include <unistd.h>                                                             
                                                                                
int footprint=0;                                                                
                                                                                
void *thread(void *arg) {                                                       
  char *storage;                                                                
                                                                                
  if ((storage = (char*) malloc(80)) == NULL) {                                 
    perror("malloc() failed");                                                  
    exit(6);                                                                    
  }                                                                             
                                                                                
  ⁄* Plan to release storage even if thread doesn't exit normally *⁄            
                                                                                
  pthread_cleanup_push(free, storage);                                          
                                                                                
  puts("thread has obtained storage and is waiting to be cancelled");           
  footprint++;                                                                  
  while (1)                                                                     
    sleep(1);                                                                   
                                                                                
  pthread_cleanup_pop(1);                                                       
}                                                                               
                                                                                
main() {                                                                        
  pthread_t thid;                                                               
                                                                                
  if (pthread_create(&thid, NULL, thread, NULL) != 0) {                         
    perror("pthread_create() error");                                           
    exit(1);                                                                    
  }                                                                             
                                                                                
  while (footprint == 0)                                                        
    sleep(1);                                                                   
                                                                                
  puts("IPT is cancelling thread");                                             
                                                                                
  if (pthread_cancel(thid) != 0) {                                              
    perror("pthread_cancel() error");                                           
    exit(3);                                                                    
  }                                                                             
                                                                                
  if (pthread_join(thid, NULL) != 0) {                                          
    perror("pthread_join() error");                                             
    exit(4);                                                                    
  }                                                                             
}                                                                               
Output:
thread has obtained storage and is waiting to be canceled
IPT is canceling thread

Related information