Anonymous | Login | 2024-09-07 15:03 UTC |
Main | My View | View Issues | Change Log | Docs |
Viewing Issue Simple Details [ Jump to Notes ] | [ Issue History ] [ Print ] | ||||||
ID | Category | Severity | Type | Date Submitted | Last Update | ||
0000811 | [1003.1(2013)/Issue7+TC1] System Interfaces | Objection | Clarification Requested | 2013-12-18 20:06 | 2019-06-10 08:55 | ||
Reporter | torvald | View Status | public | ||||
Assigned To | |||||||
Priority | normal | Resolution | Accepted As Marked | ||||
Status | Closed | ||||||
Name | Torvald Riegel | ||||||
Organization | Red Hat | ||||||
User Reference | |||||||
Section | pthread_mutex_destroy | ||||||
Page Number | 1643, 1647 | ||||||
Line Number | 53249-53251, 53423-53444 | ||||||
Interp Status | --- | ||||||
Final Accepted Text | Note: 0002267 | ||||||
Summary | 0000811: precondition for mutex destruction unclear; example contradicts normative text | ||||||
Description |
The precondition for mutex destruction is unclear because the informative example seems to contradict the normative text. The latter states: "Attempting to destroy [...] a mutex that is referenced [...] by another thread results in undefined behavior." It can be argued that a mutex can be considered "referenced" as long as a call to pthread_mutex_unlock has not yet returned to the caller. This would make the example using the reference counting incorrect because there is no synchronization between *after* unlock() in threads that don't yet destroy the mutex (i.e., no communication that unlock() calls have returned to the caller) to before the last lock/unlock whose caller will then destroy the mutex. IOW, the example program does not ensure that the mutex is not referenced during destruction. However, the conceptual unblocking of the mutex is communicated via the last thread being able to acquire the mutex; the standard should clarify what the precise precondition for destruction is. |
||||||
Desired Action |
If the intended precondition for destruction is that the mutex (i.e., the pthread_mutex_t structure) is not referenced by other threads concurrently, then the example should be removed or changed. If the intended precondition for destruction is that the mutex has been conceptually unblocked as observable to the program by being able to acquire it, then "referenced" should be clarified. I guess that it would be sufficient to state that the program is required to not have concurrent or pending lock/unlock calls anymore on this mutex; this would fit the condvar case I suspect because any mutexes 'referenced' by a condvar will also get locked eventually. Note that this choice has significant consequences for how locks can be implemented on some platforms; I can elaborate on this if this would be helpful. |
||||||
Tags | tc2-2008 | ||||||
Attached Files | |||||||
|
Notes | |
(0002081) torvald (reporter) 2013-12-18 20:07 |
This should be in "System Interfaces", sorry. |
(0002082) Don Cragun (manager) 2013-12-18 20:10 |
Category changed from Base Definitions to System Interfaces |
(0002083) dalias (reporter) 2013-12-18 20:45 |
I'd like to speak up in support of the interpretation that supports self-synchronized destruction, i.e. where the release of "reference" to a mutex happens atomically with unlocking it. As I stated on the glibc bug tracker ticket (13690) associated with this request for interpretation, I believe it is difficult for application programmers to safely use mutexes in dynamically allocated memory without this guarantee, and misuses are extremely hard to detect (reproducing the associated crashes may take months of years of cpu time). Certainly there are some cases where getting by without self-synchronized destruction is easy. For example, if you're freeing an object that's part of a larger data structure, acquiring the lock on the larger data structure before locking the individual object assures that another thread cannot still be in the tail part of the pthread_mutex_unlock call for the individual object when you obtain the mutex. But in general it's not so easy. One particularly bad case is reference-counted objects shared between threads where the thread relinquishing the last reference destroys the internal mutex and frees the object. In this case there is no additional synchronization; you have to rely on self-synchronized destruction. |
(0002167) eblake (manager) 2014-02-27 17:35 |
Here's a mailing list message (along with other messages in the same thread) that demonstrate that the current standard's silence on whether self-synchronized destruction is possible is less than ideal, in that the code ended up having to rely on a pthread_join before destroying a mutex in order to ensure that there was no overlap. https://lists.gnu.org/archive/html/qemu-devel/2014-02/msg04583.html [^] |
(0002188) geoffclare (manager) 2014-03-20 15:38 |
It would be good if we could make the normative text less vague. Where it says "a mutex that is referenced (for example, while being used in a pthread_cond_timedwait() or pthread_cond_wait()) by another thread" what other types of use besides those mentioned as examples are intended to count as "references"? Could we just change it to: "a mutex that is being used in a pthread_cond_timedwait() or pthread_cond_wait() by another thread"? |
(0002191) wlerch (reporter) 2014-03-20 16:45 |
What if the mutex is being used in a pthread_mutex_lock() by another thread -- should that not count too? |
(0002192) geoffclare (manager) 2014-03-20 16:58 |
Good point. How about: Attempting to destroy a locked mutex, or a mutex that another thread is attempting to lock, or a mutex that is being used in a pthread_cond_timedwait() or pthread_cond_wait() call by another thread, results in undefined behavior. |
(0002193) wlerch (reporter) 2014-03-20 17:21 |
Is the concern here that pthread_mutex_unlock() may be non-atomic in the sense that another thread might be able to lock (and unlock, and destroy) the mutex before pthread_mutex_unlock() is done accessing the contents of the pthread_mutex_t? |
(0002194) dalias (reporter) 2014-03-20 18:31 |
Yes, that's exactly the concern, and real world implementations (glibc) have this issue. The most problematic aspect of it is that it precludes freeing reference-counted objects, as in: pthread_mutex_lock(&obj->m); int ref = --obj->ref; pthread_mutex_unlock(&obj->m); if (!ref) { pthread_mutex_destroy(&obj->m); free(obj); } Of course nobody notices the bug because it's a race condition that gets hit once in an interval somewhere on the order of cpu-years... |
(0002195) wlerch (reporter) 2014-03-20 18:37 edited on: 2014-03-21 02:31 |
Well my naive reading of the standard would be that once pthread_mutex_unlock() has allowed another thread to get the mutex, it counts as "unlocked" by this thread, and therefore it must be safe to destroy. In other words, any implementation that has this issue has a bug. Oh, but after re-reading the original Description I (finally) see that the issue is that it *might* be claimed that a pthread_mutex_unlock() call that has unlocked the mutex but has not returned yet counts as another example of "reference", making destruction undefined; and the request is to clarify that it does not. Got it. Thanks. :) |
(0002267) geoffclare (manager) 2014-06-19 16:12 |
On page 1643 line 53249 section pthread_mutex_destroy() change from:Attempting to destroy a locked mutex or a mutex that is referenced (for example, while being used in a pthread_cond_timedwait() or pthread_cond_wait()) by another thread results in undefined behavior. to: Attempting to destroy a locked mutex, or a mutex that another thread is attempting to lock, or a mutex that is being used in a pthread_cond_timedwait() or pthread_cond_wait() call by another thread, results in undefined behavior. On page 1647 lines 53424-53425 change: A mutex can be destroyed immediately after it is unlocked. For example, consider the following code: to: A mutex can be destroyed immediately after it is unlocked. However, since attempting to destroy a locked mutex, or a mutex that another thread is attempting to lock, or a mutex that is being used in a pthread_cond_timedwait() or pthread_cond_wait() call by another thread, results in undefined behavior, care must be taken to ensure that no other thread may be referencing the mutex. On page 1647 delete lines 53426-53444. |
Issue History | |||
Date Modified | Username | Field | Change |
2013-12-18 20:06 | torvald | New Issue | |
2013-12-18 20:06 | torvald | Name | => Torvald Riegel |
2013-12-18 20:06 | torvald | Organization | => Red Hat |
2013-12-18 20:06 | torvald | Section | => pthread_mutex_destroy |
2013-12-18 20:06 | torvald | Page Number | => 1643, 1647 |
2013-12-18 20:06 | torvald | Line Number | => 53249-53251, 53423-53444 |
2013-12-18 20:07 | torvald | Note Added: 0002081 | |
2013-12-18 20:10 | Don Cragun | Interp Status | => --- |
2013-12-18 20:10 | Don Cragun | Note Added: 0002082 | |
2013-12-18 20:10 | Don Cragun | Category | Base Definitions and Headers => System Interfaces |
2013-12-18 20:45 | dalias | Note Added: 0002083 | |
2014-02-27 17:35 | eblake | Note Added: 0002167 | |
2014-03-20 15:38 | geoffclare | Note Added: 0002188 | |
2014-03-20 16:45 | wlerch | Note Added: 0002191 | |
2014-03-20 16:58 | geoffclare | Note Added: 0002192 | |
2014-03-20 17:21 | wlerch | Note Added: 0002193 | |
2014-03-20 18:31 | dalias | Note Added: 0002194 | |
2014-03-20 18:37 | wlerch | Note Added: 0002195 | |
2014-03-21 02:31 | wlerch | Note Edited: 0002195 | |
2014-06-19 16:12 | geoffclare | Note Added: 0002267 | |
2014-06-19 16:13 | geoffclare | Final Accepted Text | => Note: 0002267 |
2014-06-19 16:13 | geoffclare | Status | New => Resolved |
2014-06-19 16:13 | geoffclare | Resolution | Open => Accepted As Marked |
2014-06-19 16:13 | geoffclare | Tag Attached: tc2-2008 | |
2015-02-09 21:11 | Florian Weimer | Issue Monitored: Florian Weimer | |
2019-06-10 08:55 | agadmin | Status | Resolved => Closed |
Mantis 1.1.6[^] Copyright © 2000 - 2008 Mantis Group |