DeadlockDetection.h 2.4 KB

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