Bug 22337 - pthread_join incorrectly fails for a detached running thread
Summary: pthread_join incorrectly fails for a detached running thread
Status: NEW
Alias: None
Product: glibc
Classification: Unclassified
Component: nptl (show other bugs)
Version: 2.26
: P3 minor
Target Milestone: ---
Assignee: Adhemerval Zanella
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2017-10-23 08:40 UTC by Florian Weimer
Modified: 2017-11-03 20:02 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:
fweimer: security-


Attachments
join-detach.c (252 bytes, text/plain)
2017-10-23 08:40 UTC, Florian Weimer
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Florian Weimer 2017-10-23 08:40:31 UTC
Created attachment 10551 [details]
join-detach.c

POSIX requires that pthread_detach does not change the joinable state of a thread.  The joinable state is only set a thread creation time according to POSIX.

The attached reproducer must not terminate.  It currently fails with:

join-detach: pthread_join: Invalid argument
Comment 1 Andreas Schwab 2017-10-23 09:52:19 UTC
Where does it say that?  The point of pthread_detatch is to detach a thread, thus no longer joinable, and 2.9.2 clearly says that pthead_detach works like PTHREAD_CREATE_DETACHED.
Comment 2 Florian Weimer 2017-10-23 10:38:30 UTC
There is this sentence in 2.9.2:

“If a thread is detached, its thread ID is invalid for use as an argument in a call to pthread_detach() or pthread_join().”

Is this what you mean?

But it is not clear to me that pthread_detach actually makes the thread detached.  The effect is specified as “The pthread_detach() function shall indicate to the implementation that storage for the thread thread can be reclaimed when that thread terminates.”  Not that the thread will be detached or not joinable afterwards.
Comment 3 Andreas Schwab 2017-10-23 10:46:17 UTC
"The lifetime of a thread ID ends after the thread terminates if it was created with the detachstate attribute set to PTHREAD_CREATE_DETACHED or if pthread_detach() or pthread_join() has been called for that thread."
Comment 4 Florian Weimer 2017-10-23 10:49:36 UTC
(In reply to Andreas Schwab from comment #3)
> "The lifetime of a thread ID ends after the thread terminates if it was
> created with the detachstate attribute set to PTHREAD_CREATE_DETACHED or if
> pthread_detach() or pthread_join() has been called for that thread."

But that doesn't apply to the test case because the thread in question never exits, so the lifetime of its thread ID never ends.
Comment 5 Andreas Schwab 2017-10-23 10:57:10 UTC
Please read the rational.  It clearly says that pthread_detach dynamically detaches the thread, like PTHREAD_CREATE_DETACHED does at creation time.
Comment 6 Florian Weimer 2017-10-23 11:41:50 UTC
(In reply to Andreas Schwab from comment #5)
> Please read the rational.  It clearly says that pthread_detach dynamically
> detaches the thread, like PTHREAD_CREATE_DETACHED does at creation time.

Do you mean the rationale section for pthread_detach?  It only discusses freeing resources.  It does not describe how the joinable/detached state of the thread is impacted by pthread_detach.
Comment 7 Andreas Schwab 2017-10-23 11:49:05 UTC
It says that pthread_detach has the same effect as PTHREAD_CREATE_DETACHED.
Comment 8 Carlos O'Donell 2017-10-23 21:33:00 UTC
(In reply to Andreas Schwab from comment #7)
> It says that pthread_detach has the same effect as PTHREAD_CREATE_DETACHED.

I agree with Andreas, it is the principle of least surprise. 

Once you call pthread_detach() it *should* behave as if you'd started the thread with PTHREAD_CREATE_DETACHED.

This means pthread_join returns EINVAL (thread is not joinable) as soon as pthread_detach finishes setting joinid to itself.

The other thing to consider is this: What happens if you call pthread_detach() *while* another thread is already waiting? (this is mentioned in the comments in pthread_detach).

I think the only bug is that a pthread_join *before* a pthread_detach should result in pthread_detach returning EINVAL, but right now it looks like we return 0 (just looking at the code, would need a test case for this).
Comment 9 Florian Weimer 2017-10-30 16:33:16 UTC
I filed an issue: http://austingroupbugs.net/view.php?id=1167