| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| Expand Up | @@ -180,17 +180,57 @@ drop_gil(struct _ceval_runtime_state *ceval, PyThreadState *tstate) | |
| #endif | ||
| } | ||
|
|
||
|
|
||
| static inline int | ||
| thread_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); | ||
| } | ||
|
|
||
|
|
||
| /* Take the GIL. | ||
|
|
||
| The function saves errno at entry and restores its value at exit. | ||
|
|
||
| Exit immediately the thread if Py_Finalize() has been called and tstate is | ||
| not the thread which called Py_Finalize(). For example, exit daemon threads | ||
| which survive after Py_Finalize(). | ||
|
|
||
| tstate must be non-NULL. */ | ||
| static void | ||
| take_gil(struct _ceval_runtime_state *ceval, PyThreadState *tstate) | ||
| take_gil(PyThreadState *tstate) | ||
| { | ||
| int err = errno; | ||
|
|
||
| if (thread_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. | ||
|
|
||
| When this function is called after Py_Finalize() completed, the GIL | ||
| does no longer exist. */ | ||
| PyThread_exit_thread(); | ||
| } | ||
|
|
||
| /* ensure that tstate is valid */ | ||
| assert(!_PyMem_IsPtrFreed(tstate)); | ||
| assert(!_PyMem_IsPtrFreed(tstate->interp)); | ||
|
|
||
| struct _ceval_runtime_state *ceval = &tstate->interp->runtime->ceval; | ||
| struct _gil_runtime_state *gil = &ceval->gil; | ||
|
|
||
| /* Check someone has called PyEval_InitThreads() to create the lock */ | ||
| assert(gil_created(gil)); | ||
|
|
||
| MUTEX_LOCK(gil->mutex); | ||
|
|
||
| if (!_Py_atomic_load_relaxed(&gil->locked)) { | ||
| Expand All | @@ -206,6 +246,20 @@ take_gil(struct _ceval_runtime_state *ceval, PyThreadState *tstate) | |
|
|
||
| unsigned long interval = (gil->interval >= 1 ? gil->interval : 1); | ||
| COND_TIMED_WAIT(gil->cond, gil->mutex, interval, timed_out); | ||
|
|
||
| if (thread_must_exit(tstate)) { | ||
| /* 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 continues | ||
| to run after wait_for_thread_shutdown() and before Py_Finalize() | ||
| completes. For example, when _PyImport_Cleanup() executes Python | ||
| code. */ | ||
| MUTEX_UNLOCK(gil->mutex); | ||
|
Comment thread
Copy link
Copy Markdown
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low QualityI'm not sure if anyone else should be done here.
Sorry, something went wrong.
All reactions
Copy link
Copy Markdown
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low QualityFor example, is COND_SIGNAL(gil->cond) needed to wake up the next thread waiting on COND_TIMED_WAIT()?
Sorry, something went wrong.
All reactions
|
||
| PyThread_exit_thread(); | ||
| } | ||
|
|
||
| /* If we timed out and no switch occurred in the meantime, it is time | ||
| to ask the GIL-holding thread to drop it. */ | ||
| if (timed_out && | ||
| Expand Down Expand Up | @@ -243,6 +297,8 @@ take_gil(struct _ceval_runtime_state *ceval, PyThreadState *tstate) | |
|
|
||
| MUTEX_UNLOCK(gil->mutex); | ||
|
|
||
| assert(!thread_must_exit(tstate)); | ||
|
|
||
| errno = err; | ||
| } | ||
|
|
||
| Expand Down | ||
| Back | FazBrowse Home | New Git URL |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low QualityOk, but shouldn't you do this after COND_TIMED_WAIT below as well?
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.