Skip to content

Commit

Permalink
Ensure GIL state in pycall_pyptr_free
Browse files Browse the repository at this point in the history
This needs because this function may be called from GC sweeper on non-main threads.
  • Loading branch information
mrkn committed May 24, 2024
1 parent e02c309 commit 1b75fcf
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 1 deletion.
4 changes: 4 additions & 0 deletions ext/pycall/libpython.c
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,10 @@ pycall_init_libpython_api_table(VALUE libpython_handle)
INIT_API_TABLE_ENTRY2(PyUnicode_DecodeUTF8, PyUnicodeUCS2_DecodeUTF8, required);
INIT_API_TABLE_ENTRY2(PyUnicode_FromFormatV, PyUnicodeUCS2_FromFormatV, required);
}

INIT_API_TABLE_ENTRY(PyGILState_Check, required);
INIT_API_TABLE_ENTRY(PyGILState_Ensure, required);
INIT_API_TABLE_ENTRY(PyGILState_Release, required);
}

void
Expand Down
10 changes: 9 additions & 1 deletion ext/pycall/pycall.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,15 @@ pycall_pyptr_free(void *ptr)
fprintf(stderr, "zero refcnt object %p of type %s\n", pyobj, Py_TYPE(pyobj)->tp_name);
}
#endif /* PYCALL_DEBUG_DUMP_REFCNT */
pycall_Py_DecRef(pyobj);

if (Py_API(PyGILState_Check())) {
pycall_Py_DecRef(pyobj);
}
else {
PyGILState_STATE gstate = Py_API(PyGILState_Ensure)();
pycall_Py_DecRef(pyobj);
Py_API(PyGILState_Release)(gstate);
}
}

static size_t _PySys_GetSizeOf(PyObject *);
Expand Down
9 changes: 9 additions & 0 deletions ext/pycall/pycall_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,11 @@ PyObject * PyRuby_New(VALUE ruby_object);

/* ==== thread support ==== */

typedef enum {
PyGILState_LOCKED,
PyGILState_UNLOCKED
} PyGILState_STATE;

#if defined(PYCALL_THREAD_WIN32)
typedef DWORD pycall_tls_key;
#elif defined(PYCALL_THREAD_PTHREAD)
Expand Down Expand Up @@ -669,6 +674,10 @@ typedef struct {
PyObject * (* PyUnicode_AsUTF8String)(PyObject *);
PyObject * (* PyUnicode_DecodeUTF8)(char const*, Py_ssize_t, char const *);
PyObject * (* PyUnicode_FromFormatV)(char const*, ...);

int (* PyGILState_Check)(void);
PyGILState_STATE (* PyGILState_Ensure)(void);
void (* PyGILState_Release)(PyGILState_STATE);
} pycall_libpython_api_table_t;

pycall_libpython_api_table_t *pycall_libpython_api_table(void);
Expand Down

0 comments on commit 1b75fcf

Please sign in to comment.