pthread library error/bug?

I'm writing a library of routines to support a multi-threaded network server application that I'm writing. I have ran into a problem with using pthread_cleanup_push(3) and pthread_cleanup_pop(3). I've spent 3 hours trying to figure out why I was getting these weird compiler errors of an extra brace when I didn't see one in my program :x . Finally, I managed to pinpoint the problem to the way that these two functions...err...macros actually...are defined in pthread.h.

pthread.h:
Code:
#define         pthread_cleanup_push(cleanup_routine, cleanup_arg)              \
                {                                                               \
                        struct _pthread_cleanup_info __cleanup_info__;          \
                        __pthread_cleanup_push_imp(cleanup_routine, cleanup_arg,\
                                &__cleanup_info__);                             \
                        {

#define         pthread_cleanup_pop(execute)                                    \
                                (void)0;                                        \
                        }                                                       \
                        __pthread_cleanup_pop_imp(execute);                     \
                }

I'm not entirely sure as to WHY it was defined this way, and there's nothing in the documentation specifying any special restrictions or considerations. I'm looking at this and thinking "WTF? Why did they do it this way? :q " Some insight into the rationale behind this would be helpful. It would also be helpful to indicate in the documentation for these functions/macros that there are special considerations. This is the man page for them on my system:

pthread_cleanup_push
PTHREAD_CLEANUP_PUS... FreeBSD Library Functions Manual PTHREAD_CLEANUP_PUS...

NAME
pthread_cleanup_push -- add a cleanup function for thread exit

LIBRARY
POSIX Threads Library (libpthread, -lpthread)

SYNOPSIS
#include <pthread.h>

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

DESCRIPTION
The pthread_cleanup_push() function adds cleanup_routine to the top of
the stack of cleanup handlers that get called when the current thread
exits.

When cleanup_routine is called, it is passed arg as its only argument.

RETURN VALUES
The pthread_cleanup_push() function does not return any value.

ERRORS
None

SEE ALSO
pthread_cleanup_pop(3), pthread_exit(3)

STANDARDS
The pthread_cleanup_push() function conforms to ISO/IEC 9945-1:1996
(``POSIX.1'').

FreeBSD 9.3 July 30, 1998 FreeBSD 9.3

pthread_cleanup_pop
PTHREAD_CLEANUP_POP(3) FreeBSD Library Functions Manual PTHREAD_CLEANUP_POP(3)

NAME
pthread_cleanup_pop -- call the first cleanup routine

LIBRARY
POSIX Threads Library (libpthread, -lpthread)

SYNOPSIS
#include <pthread.h>

void
pthread_cleanup_pop(int execute);

DESCRIPTION
The pthread_cleanup_pop() function pops the top cleanup routine off of
the current threads cleanup routine stack, and, if execute is non-zero,
it will execute the function. If there is no cleanup routine then
pthread_cleanup_pop() does nothing.

RETURN VALUES
The pthread_cleanup_pop() function does not return any value.

ERRORS
None

SEE ALSO
pthread_cleanup_push(3), pthread_exit(3)

STANDARDS
The pthread_cleanup_pop() function conforms to ISO/IEC 9945-1:1996
(``POSIX.1'').

FreeBSD 9.3 July 30, 1998 FreeBSD 9.3
 
Looks pretty crazy to me. The purpose of the extra inner scope eludes me, it doesn't seem to have any use.

The original commit that added those macros is here if you want to take a closer read:

https://svnweb.freebsd.org/base?view=revision&revision=179662

Edit: Reading the commit it looks like the use of macros avoids having to allocate a structure from the heap using malloc(3). With the macros the structure is kept in the program stack and is deallocated automatically when it goes out of scope. The extra inner scope may have something to do with this as well.
 
After looking at that, I went to the POSIX standard and found that POSIX requires it. I can understand the reasoning about not wanting to use malloc(3), but at least say something about the requirements in the man page. That would have saved me a lot of time that I could have spent coding. I guess a PR is warranted.

EDIT: Bug Report 194280 has been created to track this issue.
 
Back
Top