Reputation: 837
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
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