Skip to content

Commit e66ea2f

Browse files
Merge pull request #223 from Distributive-Network/philippe/ultimate-fix-220
finalizing proxies: do not decref when shutting down
2 parents 52039ad + a9e3cc9 commit e66ea2f

File tree

3 files changed

+13
-19
lines changed

3 files changed

+13
-19
lines changed

src/PyDictProxyHandler.cc

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -167,17 +167,14 @@ bool PyDictProxyHandler::getOwnEnumerablePropertyKeys(
167167
return this->ownPropertyKeys(cx, proxy, props);
168168
}
169169

170-
// TODO not needed at this time since only called as part of cleanup function's js::DestroyContext call which is only called at cpython exit Py_AtExit in PyInit_pythonmonkey
171-
// put in some combination of the commented-out code below
172170
void PyDictProxyHandler::finalize(JS::GCContext *gcx, JSObject *proxy) const {
173-
/*PyThreadState *state = PyThreadState_Get();
174-
PyThreadState *state = PyGILState_GetThisThreadState();
175-
if (state) {
176-
PyObject *self = JS::GetMaybePtrFromReservedSlot<PyObject>(proxy, PyObjectSlot);
177-
PyGILState_STATE state = PyGILState_Ensure();
171+
// We cannot call Py_DECREF here when shutting down as the thread state is gone.
172+
// Then, when shutting down, there is only on reference left, and we don't need
173+
// to free the object since the entire process memory is being released.
174+
PyObject *self = JS::GetMaybePtrFromReservedSlot<PyObject>(proxy, PyObjectSlot);
175+
if (Py_REFCNT(self) > 1) {
178176
Py_DECREF(self);
179-
PyGILState_Release(state);
180-
}*/
177+
}
181178
}
182179

183180
bool PyDictProxyHandler::defineProperty(JSContext *cx, JS::HandleObject proxy,

src/PyListProxyHandler.cc

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2098,17 +2098,14 @@ bool PyListProxyHandler::getOwnPropertyDescriptor(
20982098
return true;
20992099
}
21002100

2101-
// TODO not needed at this time since only called as part of cleanup function's js::DestroyContext call which is only called at cpython exit Py_AtExit in PyInit_pythonmonkey
2102-
// put in some combination of the commented-out code below
21032101
void PyListProxyHandler::finalize(JS::GCContext *gcx, JSObject *proxy) const {
2104-
/*PyThreadState *state = PyThreadState_Get();
2105-
PyThreadState *state = PyGILState_GetThisThreadState();
2106-
if (state) {
2107-
PyObject *self = JS::GetMaybePtrFromReservedSlot<PyObject>(proxy, PyObjectSlot);
2108-
PyGILState_STATE state = PyGILState_Ensure();
2102+
// We cannot call Py_DECREF here when shutting down as the thread state is gone.
2103+
// Then, when shutting down, there is only on reference left, and we don't need
2104+
// to free the object since the entire process memory is being released.
2105+
PyObject *self = JS::GetMaybePtrFromReservedSlot<PyObject>(proxy, PyObjectSlot);
2106+
if (Py_REFCNT(self) > 1) {
21092107
Py_DECREF(self);
2110-
PyGILState_Release(state);
2111-
}*/
2108+
}
21122109
}
21132110

21142111
bool PyListProxyHandler::defineProperty(

src/jsTypeFactory.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ JS::Value jsTypeFactory(JSContext *cx, PyObject *object) {
180180
JS_GetClassPrototype(cx, JSProto_Object, &objectPrototype); // so that instanceof will work, not that prototype methods will
181181
proxy = js::NewProxyObject(cx, new PyDictProxyHandler(object), v, objectPrototype.get());
182182
}
183-
Py_INCREF(object); // TODO leak! clean up in finalize
183+
Py_INCREF(object);
184184
JS::SetReservedSlot(proxy, PyObjectSlot, JS::PrivateValue(object));
185185
returnType.setObject(*proxy);
186186
}

0 commit comments

Comments
 (0)