xref: /aosp_15_r20/external/pytorch/c10/util/DeadlockDetection.h (revision da0073e96a02ea20f0ac840b70461e3646d07c45)
1 #pragma once
2 
3 #include <c10/macros/Export.h>
4 #include <c10/util/Exception.h>
5 
6 /// This file provides some simple utilities for detecting common deadlocks in
7 /// PyTorch.  For now, we focus exclusively on detecting Python GIL deadlocks,
8 /// as the GIL is a wide ranging lock that is taken out in many situations.
9 /// The basic strategy is before performing an operation that may block, you
10 /// can use TORCH_ASSERT_NO_GIL_WITHOUT_PYTHON_DEP() to assert that the GIL is
11 /// not held.  This macro is to be used in contexts where no static dependency
12 /// on Python is available (we will handle indirecting a virtual call for you).
13 ///
14 /// If the GIL is held by a torchdeploy interpreter, we always report false.
15 /// If you are in a context where Python bindings are available, it's better
16 /// to directly assert on PyGILState_Check (as it avoids a vcall and also
17 /// works correctly with torchdeploy.)
18 
19 #define TORCH_ASSERT_NO_GIL_WITHOUT_PYTHON_DEP() \
20   TORCH_INTERNAL_ASSERT(                         \
21       !c10::impl::check_python_gil(),            \
22       "Holding GIL before a blocking operation!  Please release the GIL before blocking, or see https://github.com/pytorch/pytorch/issues/56297 for how to release the GIL for destructors of objects")
23 
24 namespace c10::impl {
25 
26 C10_API bool check_python_gil();
27 
28 struct C10_API PythonGILHooks {
29   virtual ~PythonGILHooks() = default;
30   // Returns true if we hold the GIL.  If not linked against Python we
31   // always return false.
32   virtual bool check_python_gil() const = 0;
33 };
34 
35 C10_API void SetPythonGILHooks(PythonGILHooks* factory);
36 
37 // DO NOT call this registerer from a torch deploy instance!  You will clobber
38 // other registrations
39 struct C10_API PythonGILHooksRegisterer {
PythonGILHooksRegistererPythonGILHooksRegisterer40   explicit PythonGILHooksRegisterer(PythonGILHooks* factory) {
41     SetPythonGILHooks(factory);
42   }
~PythonGILHooksRegistererPythonGILHooksRegisterer43   ~PythonGILHooksRegisterer() {
44     SetPythonGILHooks(nullptr);
45   }
46 };
47 
48 } // namespace c10::impl
49