|
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
|