STINNER Victor <vstin...@python.org> added the comment:

I suggest to close this issue, I don't think that it can be implemented because 
of daemon threads.

--

> This behavior should instead be triggered by the thread's interpreter 
> finalizing rather than the runtime.

What is the motivation for that?

--

take_gil() cannot access interp->finalizing since interp memory is freed during 
Python finalization.

take_gil() can only rely on a global variable like _PyRuntime to check if a 
daemon thread must exit during the Python finalization.

I modified take_gil() recently to fix 2 or 3 different crashes caused by daemon 
threads during Python finalization. Extract of ceval.c:

/* Check if a Python thread must exit immediately, rather than taking the GIL
   if Py_Finalize() has been called.

   When this function is called by a daemon thread after Py_Finalize() has been
   called, the GIL does no longer exist.

   tstate must be non-NULL. */
static inline int
tstate_must_exit(PyThreadState *tstate)
{
    /* bpo-39877: Access _PyRuntime directly rather than using
       tstate->interp->runtime to support calls from Python daemon threads.
       After Py_Finalize() has been called, tstate can be a dangling pointer:
       point to PyThreadState freed memory. */
    _PyRuntimeState *runtime = &_PyRuntime;
    PyThreadState *finalizing = _PyRuntimeState_GetFinalizing(runtime);
    return (finalizing != NULL && finalizing != tstate);
}


And simplified take_gil():

static void
take_gil(PyThreadState *tstate)
{
    if (tstate_must_exit(tstate)) {
        /* bpo-39877: If Py_Finalize() has been called and tstate is not the
           thread which called Py_Finalize(), exit immediately the thread.

           This code path can be reached by a daemon thread after Py_Finalize()
           completes. In this case, tstate is a dangling pointer: points to
           PyThreadState freed memory. */
        PyThread_exit_thread();
    }

    (... logic to acquire the GIL ...)

    if (must_exit) {
        /* bpo-36475: If Py_Finalize() has been called and tstate is not
           the thread which called Py_Finalize(), exit immediately the
           thread.

           This code path can be reached by a daemon thread which was waiting
           in take_gil() while the main thread called
           wait_for_thread_shutdown() from Py_Finalize(). */
        drop_gil(ceval, ceval2, tstate);
        PyThread_exit_thread();
    }
}

----------

_______________________________________
Python tracker <rep...@bugs.python.org>
<https://bugs.python.org/issue36479>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to