Fix autograd thread crash with python-3.9 (#50998)

Summary:
Update pybind repo to include `gil_scoped_acquire::disarm()` methods
In python_engine allocate scoped_acquire as unique_ptr and leak it if engine is finalizing for Python-3.9+

Fixes https://github.com/pytorch/pytorch/issues/50014 and https://github.com/pytorch/pytorch/issues/50893

Pull Request resolved: https://github.com/pytorch/pytorch/pull/50998

Reviewed By: ezyang

Differential Revision: D26038314

Pulled By: malfet

fbshipit-source-id: 035411e22825e8fdcf1348fed36da0bc33e16f60
This commit is contained in:
Nikita Shulga
2021-01-26 13:21:08 -08:00
committed by Facebook GitHub Bot
parent 069602e028
commit 6f3aa58d80
3 changed files with 19 additions and 2 deletions

View File

@ -48,6 +48,10 @@ Engine& PythonEngine::get_python_engine() {
return engine;
}
#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 9
#define IS_PYTHON_3_9_PLUS
#endif
void PythonEngine::thread_init(int device, const std::shared_ptr<ReadyQueue>& ready_queue, bool should_increment) {
// Increment thread usage count before acquiring the GIL
if (should_increment) {
@ -56,7 +60,11 @@ void PythonEngine::thread_init(int device, const std::shared_ptr<ReadyQueue>& re
// Create a PyThreadState, but release the GIL. This lets pybind11::gil_scoped_acquire calls
// inside thread_main acquire the GIL without having to create a new
// PyThreadState each time.
#ifdef IS_PYTHON_3_9_PLUS
auto gil = std::make_unique<pybind11::gil_scoped_acquire>();
#else
pybind11::gil_scoped_acquire gil;
#endif
pybind11::gil_scoped_release no_gil;
Engine::thread_init(device, ready_queue, false);
@ -64,6 +72,15 @@ void PythonEngine::thread_init(int device, const std::shared_ptr<ReadyQueue>& re
// Decrement the count during shutdown if we incremented earlier.
decrement_non_reentrant_thread_count();
}
#ifdef IS_PYTHON_3_9_PLUS
// Do not call PyEval_RestoreThread, PyThreadState_[Clear|DeleteCurrent] if runtime is finalizing
if (_Py_IsFinalizing()) {
no_gil.disarm();
// TODO: call disarm rather than leak gil_scoped_acquired once PyThreadState_Clear can safely be called from finalize
gil.release();
}
#endif
}
void PythonEngine::thread_on_exception(