-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[mlir][python] fix PyDenseResourceElementsAttribute finalizer #150561
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
[mlir][python] fix PyDenseResourceElementsAttribute finalizer #150561
Conversation
7f52f4c to
47afce0
Compare
2c96721 to
78a80af
Compare
|
@llvm/pr-subscribers-mlir Author: Maksim Levental (makslevental) ChangesThis PR melds #150137 and #149414 and partially reverts #124832. The summary is the PyDenseResourceElementsAttribute finalizer/deleter has/had two problems
#124832 for some reason decides to re-initialize the interpreter to avoid case 2 and runs afoul of the fact that I don't know why this decision was made (I missed the PR) but I believe we should never be calling Py_Initialize: > In an application embedding Python, this should be called before using any other Python/C API functions but we aren't embedding Python! So therefore we will only be in case when the interpreter is being finalized and in that case we should just speak the buffer. Note, lldb does a similar sort of thing for its finalizers. Full diff: https://github.com/llvm/llvm-project/pull/150561.diff 2 Files Affected:
diff --git a/mlir/lib/Bindings/Python/IRAttributes.cpp b/mlir/lib/Bindings/Python/IRAttributes.cpp
index 8f79caf08a6d0..7ddae4b5fd358 100644
--- a/mlir/lib/Bindings/Python/IRAttributes.cpp
+++ b/mlir/lib/Bindings/Python/IRAttributes.cpp
@@ -1428,6 +1428,12 @@ class PyDenseIntElementsAttribute
}
};
+// Check if the python version is less than 3.13. Py_IsFinalizing is a part
+// of stable ABI since 3.13 and before it was available as _Py_IsFinalizing.
+#if PY_VERSION_HEX < 0x030d0000
+#define Py_IsFinalizing _Py_IsFinalizing
+#endif
+
class PyDenseResourceElementsAttribute
: public PyConcreteAttribute<PyDenseResourceElementsAttribute> {
public:
@@ -1474,8 +1480,9 @@ class PyDenseResourceElementsAttribute
// The userData is a Py_buffer* that the deleter owns.
auto deleter = [](void *userData, const void *data, size_t size,
size_t align) {
- if (!Py_IsInitialized())
- Py_Initialize();
+ if (Py_IsFinalizing())
+ return;
+ assert(Py_IsInitialized() && "expected interpreter to be initialized");
Py_buffer *ownedView = static_cast<Py_buffer *>(userData);
nb::gil_scoped_acquire gil;
PyBuffer_Release(ownedView);
diff --git a/mlir/test/python/ir/array_attributes.py b/mlir/test/python/ir/array_attributes.py
index ef1d835fc6401..67b934dd19bdb 100644
--- a/mlir/test/python/ir/array_attributes.py
+++ b/mlir/test/python/ir/array_attributes.py
@@ -617,3 +617,18 @@ def test_attribute(context, mview):
# CHECK: BACKING MEMORY DELETED
# CHECK: EXIT FUNCTION
print("EXIT FUNCTION")
+
+
+# CHECK-LABEL: TEST: testDanglingResource
+print("TEST: testDanglingResource")
+# see https://github.com/llvm/llvm-project/pull/149414, https://github.com/llvm/llvm-project/pull/150137
+# This error occurs only when there is an alive context with a DenseResourceElementsAttr
+# in the end of the program, so we put it here without an encapsulating function.
+ctx = Context()
+
+with ctx, Location.unknown():
+ DenseResourceElementsAttr.get_from_buffer(
+ memoryview(np.array([1, 2, 3])),
+ "some_resource",
+ RankedTensorType.get((3,), IntegerType.get_signed(32)),
+ )
|
|
@mamanain if you tell me your email I can update the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for this! This seems to be what was causing issues on our end. It now works in python 3.11.
fa718cb to
8d90a49
Compare
Co-authored-by: Anton Korobeynikov <[email protected]> Co-authored-by: Max Manainen <[email protected]>
8d90a49 to
e5d3fd3
Compare
…50561) This PR melds llvm#150137 and llvm#149414 *and* partially reverts llvm#124832. The summary is the `PyDenseResourceElementsAttribute` finalizer/deleter has/had two problems 1. wasn't threadsafe (can be called from a different thread than that which currently holds the GIL) 2. can be called while the interpreter is "not initialized" llvm#124832 for some reason decides to re-initialize the interpreter to avoid case 2 and runs afoul of the fact that `Py_IsInitialized` can be false during the finalization of the interpreter itself (e.g., at the end of a script). I don't know why this decision was made (I missed the PR) but I believe we should never be calling [Py_Initialize](https://docs.python.org/3/c-api/init.html#c.Py_Initialize): > In an application \*\*\*\***embedding Python**\*\*\*\*, this should be called before using any other Python/C API functions **but we aren't embedding Python**! So therefore we will only be in case 2 when the interpreter is being finalized and in that case we should just leak the buffer. Note, [lldb](https://github.com/llvm/llvm-project/blob/548ca9e97673a168023a616d311d901ca04b29a3/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp#L81-L93) does a similar sort of thing for its finalizers. Co-authored-by: Anton Korobeynikov <[email protected]> Co-authored-by: Max Manainen <[email protected]> Co-authored-by: Anton Korobeynikov <[email protected]> Co-authored-by: Max Manainen <[email protected]>
|
@makslevental Likely we'd not need the check at all. See #152226 for similar LLDB change (and notes around). |
Isn't that the original version prior to #124832? Ie isn't that bug reporting that we do indeed sometimes release when |
It seems, there are multiple cases here:
If I'm reading the pytorch version and Py_buffer *ownedView = static_cast<Py_buffer *>(userData);
if (Py_IsInitialized()) {
nb::gil_scoped_acquire gil;
PyBuffer_Release(ownedView);
}
delete ownedView; |
|
yea sure this seems reasonable - do you want to send the PR that removes |
This PR melds #150137 and #149414 and partially reverts #124832.
The summary is the
PyDenseResourceElementsAttributefinalizer/deleter has/had two problems#124832 for some reason decides to re-initialize the interpreter to avoid case 2 and runs afoul of the fact that
Py_IsInitializedcan be false during the finalization of the interpreter itself (e.g., at the end of a script).I don't know why this decision was made (I missed the PR) but I believe we should never be calling Py_Initialize:
but we aren't embedding Python!
So therefore we will only be in case 2 when the interpreter is being finalized and in that case we should just leak the buffer.
Note, lldb does a similar sort of thing for its finalizers.
Co-authored-by: Anton Korobeynikov [email protected]
Co-authored-by: Max Manainen [email protected]