Hi,
Some questions:
For backwards compatibility, all thread states created by existing APIs will remain daemon by default.
- Which “existing APIs”? C ones? Python ones?
- Why are we concerned about backwards compatibility? Do we really view hanging the thread as a feature?
int PyThreadState_SetDaemon(int is_daemon)
Set the attached thread state as non-daemon or daemon.
Shouldn’t there be a PyThreadState_GetDaemon counterpart?
PyInterpreterState *PyInterpreterState_Hold(void)
The caller must have an attached thread state, and cannot returnNULL.
What cannot return NULL here? The caller? PyInterpreterState_Hold?
PyInterpreterState *PyInterpreterState_Lookup(int64_t interp_id)
Similar toPyInterpreterState_Hold(), but looks up an interpreter based on an ID (seePyInterpreterState_GetID()). This has the benefit of allowing the interpreter to finalize in cases where the thread might not start, such as inside of a signal handler.
Is this API function really signal-safe? That sounds like a very constraining requirement for a function that will probably have to access a mutable global structure.
int PyThreadState_Ensure(PyInterpreterState *interp)
The interpreter’s interp reference count is decremented by one.
Are you sure that’s safe to do? I would expect PyThreadState_Release to decref the interpreter, not PyThreadState_Ensure. Otherwise, what happens if there is a Py_BEGIN_ALLOW_THREADS / Py_END_ALLOW_THREADS pair inside the
PyThreadState_Ensure / PyThreadState_Release pair? Could Py_END_ALLOW_THREADS fail reacquiring the interpreter?
void PyThreadState_Release()
Detach and destroy the attached thread state set byPyThreadState_Ensure().
It doesn’t always destroy the thread state, does it? It should only do so if the thread state was created by the matching PyThreadState_Ensure() call.
I would also expect the PEP to answer a couple more questions:
- Are nested pairs of
PyThreadState_Ensure()andPyThreadState_Release()calls supported? - What is the use case for
PyInterpreterState_Lookup()? Is it when you don’t want to keep a strong reference to an interpreter? Is the interpreter id guaranteed to be unique for the entire process call (i.e. it cannot be recycled after the interpreter was destroyed)? The PyInterpreterState_GetID doc doesn’t say so. - How does this change the shutdown sequence? Does
Py_FinalizeExwait for all subinterpreters to be released (this could certainly introduce new deadlocks)? Or doesPy_FinalizeExonly finalize the main interpreter, letting subinterpreters die when their refcount drops to zero?