From: Kristian V. D. V. <va...@li...> - 2008-11-01 12:18:56
|
On Sat, 2008-11-01 at 11:42 +0100, Stefano D'Angelo wrote: > I investigated a bit into Syllable's source code and it seems like > some weird stuff is going on... First, in pthread_exit(), this cycle > seems to be broken: > > 231 while ( cleanup ) > 232 { > 233 if ( cleanup->routine ) > 234 (*cleanup->routine) (cleanup->arg); > 235 cleanup = cleanup->prev; > 236 free( cleanup ); > 237 } > > since after the first loop, cleanup points to a freed memory location, > which shouldn't be considered valid any more (unless you have very > very strange memory handling routines/conventions, but I doubt that). Believe it or not that loop is actually O.K. It works backwards through the list, calling the cleanup handlers and then freeing the structures as it goes. For the first item in the list, prev will be NULL and free(NULL) is a valid no-op, and the loop will then exit. I admit it is non-obvious. > Going back to the original problem, it seems like pthread_exit() > completely destroys the thread, which is not a POSIX-compliant > behaviour, since it won't be found by pthread_join()s happening after > the thread has terminated. > > This would be ok for PTHREAD_CREATE_DETACHED threads, but the POSIX > standards states that the default detachstate is > PTHREAD_CREATE_JOINABLE. The OpenGroup spec says: "The pthread_join() function suspends execution of the calling thread until the target thread terminates, unless the target thread has already terminated. On return from a successful pthread_join() call with a non-NULL value_ptr argument, the value passed to pthread_exit() by the terminating thread is made available in the location referenced by value_ptr. When a pthread_join() returns successfully, the target thread has been terminated. The results of multiple simultaneous calls to pthread_join() specifying the same target thread are undefined. If the thread calling pthread_join() is canceled, then the target thread will not be detached. [ESRCH] No thread could be found corresponding to that specified by the given thread ID." which is what the current implementation does: if pthread_join() is called on a thread that has already called pthread_exit() it returns ESRCH. However it seems I have been tripped up by "When a pthread_join() returns successfully, the target thread has been terminated."! Reading that now my interpretation is that pthread_join() should return immediately when called on a thread that has exited, rather than returning ESRCH. I *think* there is a way to fix this, sort of: wait_for_thread() will return -ECHILD if the target thread does not exist, which can be interpreted as "Thread has exited". However there is then no way to detect cases where the thread ID is invalid I.e. to return ESRCH, but this would seem to be a less important edge case. -- Vanders http://www.syllable.org |