Open
Description
Feature or enhancement
Proposal:
It would be helpful to expose _PyCriticalSection_BeginMutex
as a public API.
There are times when one does not have really have a PyObject
, but still might want to use a critical section. For example, we wanted to use a critical section to protect some initialization code in a C extension module, where we wanted to write something like this:
static PyMutex mu;
static PyObject* mymodule = nullptr;
// It is important that we use a critical section here rather than a regular
// PyMutex, say 'M', because we need to avoid the following deadlock:
// * thread T1 holds M and calls ImportModule, which attempts to acquire a
// critical section C.
// * thread T2 holds critical section C and attempts to call this code and
// acquire M.
// In general, if you're going to hold a lock while calling into Python code, it had better be a critical section.
PyCriticalSection cs;
_PyCriticalSection_BeginMutex(&cs, &mu);
if (!mymodule) {
PyObject *m = PyImport_ImportModule("mymodule");
// Importing may have released the critical section, so it is possible
// another thread might have populated mymodule. Make sure we clean up after
// ourselves in that case.
std::swap(mymodule, m);
Py_XDECREF(m);
}
PyCriticalSection_End(&cs);
Currently one would have to write something like the following instead:
static PyObject object_for_mu; // Not really an object, we just want its mutex.
static PyObject* mymodule = nullptr;
PyCriticalSection cs;
PyCriticalSection_Begin(&cs, &object_for_mu);
if (!mymodule) {
PyObject *m = PyImport_ImportModule("mymodule");
std::swap(mymodule, m);
Py_XDECREF(m);
}
PyCriticalSection_End(&cs);
Has this already been discussed elsewhere?
This is a minor feature, which does not need previous discussion elsewhere
Links to previous discussion of this feature:
No response