-
-
Notifications
You must be signed in to change notification settings - Fork 34.5k
gh-125053: Document that ob_mutex must only be used via critical section API #144599
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
8c202f0
72f2d44
5e1ba4a
a0bc324
49a4fa3
8129308
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -384,6 +384,55 @@ Important Considerations | |
| internal extension state, standard mutexes or other synchronization | ||
| primitives might be more appropriate. | ||
|
|
||
| .. _per-object-locks: | ||
|
|
||
| Per-Object Locks (``ob_mutex``) | ||
| ............................... | ||
|
|
||
| In the free-threaded build, each Python object contains a :c:member:`~PyObject.ob_mutex` | ||
| field of type :c:type:`PyMutex`. This mutex is **reserved for use by the | ||
| critical section API** (:c:macro:`Py_BEGIN_CRITICAL_SECTION` / | ||
| :c:macro:`Py_END_CRITICAL_SECTION`). | ||
|
|
||
| .. warning:: | ||
|
|
||
| Do **not** lock ``ob_mutex`` directly with ``PyMutex_Lock(&obj->ob_mutex)``. | ||
| Mixing direct ``PyMutex_Lock`` calls with the critical section API on the | ||
| same mutex can cause deadlocks, because the critical section implementation | ||
| may suspend and release its locks when contention is detected. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I don't think this is related to why it may deadlock. I'd remove everything from ", because the ..." onwards.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. addressed the issue. |
||
|
|
||
| Even if your own code never uses critical sections on a particular object type, | ||
| **CPython internals may use the critical section API on any Python object**. | ||
| For example, the garbage collector or other interpreter internals may enter a | ||
| critical section on your object. If your code holds ``ob_mutex`` directly at | ||
| that point, a deadlock can occur. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think the garbage collector ever acquires critical sections on objects. Maybe just: Even if your own code never uses critical sections on a particular object type,
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
It sounds redundant with the above warning. Is it worth it to say it again?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, seems fine to get rid of that as well to me. |
||
|
|
||
| If your extension type needs its own lock, add a separate :c:type:`PyMutex` | ||
| field (or another synchronization primitive) to your object struct. | ||
| :c:type:`PyMutex` is very lightweight — it is only one byte — so there is | ||
| negligible cost to having an additional one:: | ||
|
|
||
| /* WRONG — do not lock ob_mutex directly */ | ||
|
kumaraditya303 marked this conversation as resolved.
Outdated
|
||
| PyMutex_Lock(&obj->ob_mutex); | ||
| ... | ||
| PyMutex_Unlock(&obj->ob_mutex); | ||
|
|
||
| /* RIGHT — use critical sections for ob_mutex */ | ||
| Py_BEGIN_CRITICAL_SECTION(obj); | ||
| ... | ||
| Py_END_CRITICAL_SECTION(); | ||
|
|
||
| /* RIGHT — use your own mutex for your own state */ | ||
| typedef struct { | ||
| PyObject_HEAD | ||
| PyMutex my_mutex; /* separate lock for extension state */ | ||
| int my_data; | ||
| } MyObject; | ||
|
|
||
| PyMutex_Lock(&self->my_mutex); | ||
| self->my_data++; | ||
| PyMutex_Unlock(&self->my_mutex); | ||
|
|
||
|
|
||
| Building Extensions for the Free-Threaded Build | ||
| =============================================== | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.