Skip to content

Commit dd0aaed

Browse files
committed
fix: clean up SpiderMonkey when the PythonMonkey module gets destroyed
We cannot use `Py_AtExit(cleanup);` because the GIL is unavailable after Python finalization, no more Python APIs can be called.
1 parent 3453696 commit dd0aaed

File tree

1 file changed

+18
-1
lines changed

1 file changed

+18
-1
lines changed

src/modules/pythonmonkey/pythonmonkey.cc

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,12 +303,20 @@ PyTypeObject JSObjectItemsProxyType = {
303303
};
304304

305305
static void cleanup() {
306+
// Clean up the PythonMonkey module
307+
Py_XDECREF(PythonMonkey_Null);
308+
Py_XDECREF(PythonMonkey_BigInt);
309+
310+
// Clean up SpiderMonkey
306311
delete autoRealm;
307312
delete global;
308313
if (GLOBAL_CX) JS_DestroyContext(GLOBAL_CX);
309314
delete JOB_QUEUE;
310315
JS_ShutDown();
311316
}
317+
static void cleanup(PyObject *) {
318+
cleanup();
319+
}
312320

313321
static PyObject *collect(PyObject *self, PyObject *args) {
314322
JS_GC(GLOBAL_CX);
@@ -550,7 +558,6 @@ PyMODINIT_FUNC PyInit_pythonmonkey(void)
550558
PyErr_SetString(SpiderMonkeyError, "Spidermonkey could not be initialized.");
551559
return NULL;
552560
}
553-
Py_AtExit(cleanup);
554561

555562
GLOBAL_CX = JS_NewContext(JS::DefaultHeapMaxBytes);
556563
if (!GLOBAL_CX) {
@@ -643,6 +650,16 @@ PyMODINIT_FUNC PyInit_pythonmonkey(void)
643650
if (pyModule == NULL)
644651
return NULL;
645652

653+
// Clean up SpiderMonkey when the PythonMonkey module gets destroyed (module.___cleanup is GCed)
654+
// The `cleanup` function will be called automatically when this PyCapsule gets GCed
655+
// We cannot use `Py_AtExit(cleanup);` because the GIL is unavailable after Python finalization, no more Python APIs can be called.
656+
PyObject *autoDestructor = PyCapsule_New(&pythonmonkey, NULL, cleanup);
657+
if (PyModule_AddObject(pyModule, "___cleanup", autoDestructor) < 0) {
658+
Py_DECREF(autoDestructor);
659+
Py_DECREF(pyModule);
660+
return NULL;
661+
}
662+
646663
Py_INCREF(&NullType);
647664
if (PyModule_AddObject(pyModule, "null", (PyObject *)&NullType) < 0) {
648665
Py_DECREF(&NullType);

0 commit comments

Comments
 (0)