PTHREAD_CLEANUP(3)                                          PTHREAD_CLEANUP(3)

       pthread_cleanup_push,                              pthread_cleanup_pop,
       pthread_cleanup_push_defer_np, pthread_cleanup_pop_restore_np - install
       and remove cleanup handlers

       #include <pthread.h>

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

       void pthread_cleanup_pop(int execute);

       void   pthread_cleanup_push_defer_np(void  (*routine)  (void  *),  void

       void pthread_cleanup_pop_restore_np(int execute);

       Cleanup handlers are functions that get called  when  a  thread  termi-
       nates,  either  by  calling pthread_exit(3) or because of cancellation.
       Cleanup handlers are installed and removed following a stack-like  dis-

       The  purpose of cleanup handlers is to free the resources that a thread
       may hold at the time it terminates. In particular, if a thread exits or
       is cancelled while it owns a locked mutex, the mutex will remain locked
       forever and prevent other threads from executing normally. The best way
       to  avoid  this is, just before locking the mutex, to install a cleanup
       handler whose effect is to unlock the mutex. Cleanup  handlers  can  be
       used  similarly  to  free blocks allocated with malloc(3) or close file
       descriptors on thread termination.

       pthread_cleanup_push installs the routine function with argument arg as
       a   cleanup   handler.   From   this   point   on   to   the   matching
       pthread_cleanup_pop, the function routine will be called with arguments
       arg  when  the  thread terminates, either through pthread_exit(3) or by
       cancellation. If several cleanup handlers are  active  at  that  point,
       they  are  called in LIFO order: the most recently installed handler is
       called first.

       pthread_cleanup_pop removes the most recently  installed  cleanup  han-
       dler.  If  the execute argument is not 0, it also executes the handler,
       by calling the routine function with arguments  arg.   If  the  execute
       argument is 0, the handler is only removed but not executed.

       Matching  pairs  of  pthread_cleanup_push  and pthread_cleanup_pop must
       occur in the same function, at the same level of block nesting.   Actu-
       ally,  pthread_cleanup_push and pthread_cleanup_pop are macros, and the
       expansion of pthread_cleanup_push introduces an open brace {  with  the
       matching  closing  brace  }  being  introduced  by the expansion of the
       matching pthread_cleanup_pop.

       pthread_cleanup_push_defer_np is a non-portable extension that combines
       pthread_cleanup_push and pthread_setcanceltype(3).  It pushes a cleanup
       handler just as pthread_cleanup_push does, but also saves  the  current
       cancellation  type  and  sets it to deferred cancellation. This ensures
       that the cleanup mechanism is effective even if  the  thread  was  ini-
       tially in asynchronous cancellation mode.

       pthread_cleanup_pop_restore_np  pops  a  cleanup  handler introduced by
       pthread_cleanup_push_defer_np, and restores the  cancellation  type  to
       its value at the time pthread_cleanup_push_defer_np was called.

       pthread_cleanup_push_defer_np  and  pthread_cleanup_pop_restore_np must
       occur in matching pairs, at the same level of block nesting.

       The following sequence

              pthread_cleanup_push_defer_np(routine, arg);

       is functionally equivalent to (but  more  compact  and  more  efficient

              { int oldtype;
                pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype);
                pthread_cleanup_push(routine, arg);
                pthread_setcanceltype(oldtype, NULL);



       Xavier Leroy <>

       pthread_exit(3), pthread_cancel(3), pthread_setcanceltype(3).

       Here  is how to lock a mutex mut in such a way that it will be unlocked
       if the thread is canceled while mut is locked:

              pthread_cleanup_push(pthread_mutex_unlock, (void *) &mut);
              /* do some work */

       Equivalently, the last two lines can be replaced by


       Notice that the code above is safe only in deferred  cancellation  mode
       (see  pthread_setcanceltype(3)).   In asynchronous cancellation mode, a
       cancellation    can    occur    between    pthread_cleanup_push     and
       pthread_mutex_lock,     or     between     pthread_mutex_unlock     and
       pthread_cleanup_pop, resulting in both cases in the  thread  trying  to
       unlock  a mutex not locked by the current thread. This is the main rea-
       son why asynchronous cancellation is difficult to use.

       If the code above must also work  in  asynchronous  cancellation  mode,
       then  it  must  switch  to  deferred mode for locking and unlocking the

              pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype);
              pthread_cleanup_push(pthread_mutex_unlock, (void *) &mut);
              /* do some work */
              pthread_setcanceltype(oldtype, NULL);

       The code above can be rewritten in a more compact  and  more  efficient
       way, using the non-portable functions pthread_cleanup_push_defer_np and

              pthread_cleanup_push_restore_np(pthread_mutex_unlock, (void *) &mut);
              /* do some work */

                                 LinuxThreads               PTHREAD_CLEANUP(3)