Skip to content

Commit 22629fd

Browse files
committed
Ensure GIL state in pycall_pyptr_free
This needs because this function may be called from GC sweeper on non-main threads.
1 parent 9a40e6b commit 22629fd

File tree

3 files changed

+22
-1
lines changed

3 files changed

+22
-1
lines changed

ext/pycall/libpython.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,10 @@ pycall_init_libpython_api_table(VALUE libpython_handle)
217217
INIT_API_TABLE_ENTRY2(PyUnicode_DecodeUTF8, PyUnicodeUCS2_DecodeUTF8, required);
218218
INIT_API_TABLE_ENTRY2(PyUnicode_FromFormatV, PyUnicodeUCS2_FromFormatV, required);
219219
}
220+
221+
INIT_API_TABLE_ENTRY(PyGILState_Check, required);
222+
INIT_API_TABLE_ENTRY(PyGILState_Ensure, required);
223+
INIT_API_TABLE_ENTRY(PyGILState_Release, required);
220224
}
221225

222226
void

ext/pycall/pycall.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,15 @@ pycall_pyptr_free(void *ptr)
139139
fprintf(stderr, "zero refcnt object %p of type %s\n", pyobj, Py_TYPE(pyobj)->tp_name);
140140
}
141141
#endif /* PYCALL_DEBUG_DUMP_REFCNT */
142-
pycall_Py_DecRef(pyobj);
142+
143+
if (Py_API(PyGILState_Check())) {
144+
pycall_Py_DecRef(pyobj);
145+
}
146+
else {
147+
PyGILState_STATE gstate = Py_API(PyGILState_Ensure)();
148+
pycall_Py_DecRef(pyobj);
149+
Py_API(PyGILState_Release)(gstate);
150+
}
143151
}
144152

145153
static size_t _PySys_GetSizeOf(PyObject *);

ext/pycall/pycall_internal.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,11 @@ PyObject * PyRuby_New(VALUE ruby_object);
519519

520520
/* ==== thread support ==== */
521521

522+
typedef enum {
523+
PyGILState_LOCKED,
524+
PyGILState_UNLOCKED
525+
} PyGILState_STATE;
526+
522527
#if defined(PYCALL_THREAD_WIN32)
523528
typedef DWORD pycall_tls_key;
524529
#elif defined(PYCALL_THREAD_PTHREAD)
@@ -669,6 +674,10 @@ typedef struct {
669674
PyObject * (* PyUnicode_AsUTF8String)(PyObject *);
670675
PyObject * (* PyUnicode_DecodeUTF8)(char const*, Py_ssize_t, char const *);
671676
PyObject * (* PyUnicode_FromFormatV)(char const*, ...);
677+
678+
int (* PyGILState_Check)(void);
679+
PyGILState_STATE (* PyGILState_Ensure)(void);
680+
void (* PyGILState_Release)(PyGILState_STATE);
672681
} pycall_libpython_api_table_t;
673682

674683
pycall_libpython_api_table_t *pycall_libpython_api_table(void);

0 commit comments

Comments
 (0)