pthread_cleanup_push causes Syntax error

2019-05-16 12:07发布

问题:

I try to add a section to my code which is able to unlock the mutex in a case of cancellation. This may happen and would cause a deadlock. Therefore I tried to add pthread_cleanup_push(cleanup_unlock_mutex, &mutex_ftdi); but this line cause a syntax error from the line where I add it till the end of the code file. If I comment the code line the program will compile without any error. What I'm doing wrong?

void cleanup_unlock_mutex(void *p){
    pthread_mutex_unlock(p);
}

....... }else{
                for(unsigned count=0; count <= number_of_requests; count++){
                    pthread_cleanup_push(cleanup_unlock_mutex, &mutex_ftdi);
                    pthread_mutex_lock(&mutex_ftdi);
                    process_requests(count, numberofthread);
                    pthread_mutex_unlock(&mutex_ftdi);
                }
            } // compiler error: error: expected ‘while’ before ‘}’ token
..........

All other functions in the file get the warning: ISO C forbids nested functions [-pedantic].

回答1:

You must call pthread_cleanup_push() and pthread_cleanup_pop() in matching pairs, and your snippet doesn't have the pthread_cleanup_pop() call.

The docs at http://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_cleanup_pop.html explain why:

These functions may be implemented as macros. The application shall ensure that they appear as statements, and in pairs within the same lexical scope (that is, the pthread_cleanup_push() macro may be thought to expand to a token list whose first token is '{' with pthread_cleanup_pop() expanding to a token list whose last token is the corresponding '}' ).

To make this concrete, one possible implementation, taken from glibc's nptl/sysdeps/pthread/pthread.h:

/* Install a cleanup handler: ROUTINE will be called with arguments ARG
   when the thread is canceled or calls pthread_exit.  ROUTINE will also
   be called with arguments ARG when the matching pthread_cleanup_pop
   is executed with non-zero EXECUTE argument.

   pthread_cleanup_push and pthread_cleanup_pop are macros and must always
   be used in matching pairs at the same nesting level of braces.  */
#  define pthread_cleanup_push(routine, arg) \
  do {                                        \
    __pthread_cleanup_class __clframe (routine, arg)

/* Remove a cleanup handler installed by the matching pthread_cleanup_push.
   If EXECUTE is non-zero, the handler function is called. */
#  define pthread_cleanup_pop(execute) \
    __clframe.__setdoit (execute);                        \
  } while (0)


标签: c pthreads mutex