tomKPZ
tomKPZ

Reputation: 837

Passing stack variables to pthread_cleanup_push

I have a thread that uses a file descriptor and must close() the file descriptor when cancelled. The pseudocode looks like:

static void thread_cleanup(void *args)
{
    int *fd = (int *)args;
    close(*fd);
}

void *thread(void *arg)
{
    int fd = open(...);
    ...
    pthread_cleanup_push(thread_cleanup, &fd);
    ....
}

One option I had was to pass fd casted to a void * from thread, and have thread_cleanup cast it back to an int, but this may cause problems if sizeof(int) != sizeof(void *). My question is: is passing stack variables as in the pseudocode safe when used in this fashion?

Upvotes: 4

Views: 743

Answers (1)

R.. GitHub STOP HELPING ICE
R.. GitHub STOP HELPING ICE

Reputation: 215287

Your concern about sizeof seems to be based on some confusion. No conversion between int and void * is taking place, so whether they are the same size, or whether the values of one can be represented in the other, is irrelevant. What's happening is that the address of fd, a pointer value of type int *, is being converted to void * and back to int *. This is the whole point of void * and is perfectly correct usage.

As for whether it matters that the pointed-to object is "on the stack" (an object with automatic storage duration in the function where the cleanup handler is pushed/popped), the answer is yes, but your usage is okay.

Formally (as the current specification in POSIX is written), any object whose lifetime did not end before cancellation was acted upon still exists and can be accessed from all the cleanup handlers. However, this seems to be a mistake in the standard, as it conflicts with the Rationale document which supports unwinding-based implementations (like most real-world implementations) where cancellation cleanup handlers execute at the block context where they were pushed. Since the object int fd; in the function thread has lifetime associated with the containing block outside the pthread_cleanup_push block, it's perfectly safe to access it from the cleanup handler thread_cleanup.

Upvotes: 1

Related Questions