TThreadState.hpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543
  1. #ifndef GREENLET_THREAD_STATE_HPP
  2. #define GREENLET_THREAD_STATE_HPP
  3. #include <ctime>
  4. #include <stdexcept>
  5. #include <atomic>
  6. #include "greenlet_internal.hpp"
  7. #include "greenlet_refs.hpp"
  8. #include "greenlet_thread_support.hpp"
  9. using greenlet::refs::BorrowedObject;
  10. using greenlet::refs::BorrowedGreenlet;
  11. using greenlet::refs::BorrowedMainGreenlet;
  12. using greenlet::refs::OwnedMainGreenlet;
  13. using greenlet::refs::OwnedObject;
  14. using greenlet::refs::OwnedGreenlet;
  15. using greenlet::refs::OwnedList;
  16. using greenlet::refs::PyErrFetchParam;
  17. using greenlet::refs::PyArgParseParam;
  18. using greenlet::refs::ImmortalString;
  19. using greenlet::refs::CreatedModule;
  20. using greenlet::refs::PyErrPieces;
  21. using greenlet::refs::NewReference;
  22. namespace greenlet {
  23. /**
  24. * Thread-local state of greenlets.
  25. *
  26. * Each native thread will get exactly one of these objects,
  27. * automatically accessed through the best available thread-local
  28. * mechanism the compiler supports (``thread_local`` for C++11
  29. * compilers or ``__thread``/``declspec(thread)`` for older GCC/clang
  30. * or MSVC, respectively.)
  31. *
  32. * Previously, we kept thread-local state mostly in a bunch of
  33. * ``static volatile`` variables in the main greenlet file.. This had
  34. * the problem of requiring extra checks, loops, and great care
  35. * accessing these variables if we potentially invoked any Python code
  36. * that could release the GIL, because the state could change out from
  37. * under us. Making the variables thread-local solves this problem.
  38. *
  39. * When we detected that a greenlet API accessing the current greenlet
  40. * was invoked from a different thread than the greenlet belonged to,
  41. * we stored a reference to the greenlet in the Python thread
  42. * dictionary for the thread the greenlet belonged to. This could lead
  43. * to memory leaks if the thread then exited (because of a reference
  44. * cycle, as greenlets referred to the thread dictionary, and deleting
  45. * non-current greenlets leaked their frame plus perhaps arguments on
  46. * the C stack). If a thread exited while still having running
  47. * greenlet objects (perhaps that had just switched back to the main
  48. * greenlet), and did not invoke one of the greenlet APIs *in that
  49. * thread, immediately before it exited, without some other thread
  50. * then being invoked*, such a leak was guaranteed.
  51. *
  52. * This can be partly solved by using compiler thread-local variables
  53. * instead of the Python thread dictionary, thus avoiding a cycle.
  54. *
  55. * To fully solve this problem, we need a reliable way to know that a
  56. * thread is done and we should clean up the main greenlet. On POSIX,
  57. * we can use the destructor function of ``pthread_key_create``, but
  58. * there's nothing similar on Windows; a C++11 thread local object
  59. * reliably invokes its destructor when the thread it belongs to exits
  60. * (non-C++11 compilers offer ``__thread`` or ``declspec(thread)`` to
  61. * create thread-local variables, but they can't hold C++ objects that
  62. * invoke destructors; the C++11 version is the most portable solution
  63. * I found). When the thread exits, we can drop references and
  64. * otherwise manipulate greenlets and frames that we know can no
  65. * longer be switched to.
  66. *
  67. * There are two small wrinkles. The first is that when the thread
  68. * exits, it is too late to actually invoke Python APIs: the Python
  69. * thread state is gone, and the GIL is released. To solve *this*
  70. * problem, our destructor uses ``Py_AddPendingCall`` to transfer the
  71. * destruction work to the main thread.
  72. *
  73. * The second is that once the thread exits, the thread local object
  74. * is invalid and we can't even access a pointer to it, so we can't
  75. * pass it to ``Py_AddPendingCall``. This is handled by actually using
  76. * a second object that's thread local (ThreadStateCreator) and having
  77. * it dynamically allocate this object so it can live until the
  78. * pending call runs.
  79. */
  80. class ThreadState {
  81. private:
  82. // As of commit 08ad1dd7012b101db953f492e0021fb08634afad
  83. // this class needed 56 bytes in o Py_DEBUG build
  84. // on 64-bit macOS 11.
  85. // Adding the vector takes us up to 80 bytes ()
  86. /* Strong reference to the main greenlet */
  87. OwnedMainGreenlet main_greenlet;
  88. /* Strong reference to the current greenlet. */
  89. OwnedGreenlet current_greenlet;
  90. /* Strong reference to the trace function, if any. */
  91. OwnedObject tracefunc;
  92. typedef std::vector<PyGreenlet*, PythonAllocator<PyGreenlet*> > deleteme_t;
  93. /* A vector of raw PyGreenlet pointers representing things that need
  94. deleted when this thread is running. The vector owns the
  95. references, but you need to manually INCREF/DECREF as you use
  96. them. We don't use a vector<refs::OwnedGreenlet> because we
  97. make copy of this vector, and that would become O(n) as all the
  98. refcounts are incremented in the copy.
  99. */
  100. deleteme_t deleteme;
  101. #ifdef GREENLET_NEEDS_EXCEPTION_STATE_SAVED
  102. void* exception_state;
  103. #endif
  104. #ifdef Py_GIL_DISABLED
  105. static std::atomic<std::clock_t> _clocks_used_doing_gc;
  106. #else
  107. static std::clock_t _clocks_used_doing_gc;
  108. #endif
  109. static ImmortalString get_referrers_name;
  110. static PythonAllocator<ThreadState> allocator;
  111. G_NO_COPIES_OF_CLS(ThreadState);
  112. // Allocates a main greenlet for the thread state. If this fails,
  113. // exits the process. Called only during constructing a ThreadState.
  114. MainGreenlet* alloc_main()
  115. {
  116. PyGreenlet* gmain;
  117. /* create the main greenlet for this thread */
  118. gmain = reinterpret_cast<PyGreenlet*>(PyType_GenericAlloc(&PyGreenlet_Type, 0));
  119. if (gmain == NULL) {
  120. throw PyFatalError("alloc_main failed to alloc"); //exits the process
  121. }
  122. MainGreenlet* const main = new MainGreenlet(gmain, this);
  123. assert(Py_REFCNT(gmain) == 1);
  124. assert(gmain->pimpl == main);
  125. return main;
  126. }
  127. public:
  128. static void* operator new(size_t UNUSED(count))
  129. {
  130. return ThreadState::allocator.allocate(1);
  131. }
  132. static void operator delete(void* ptr)
  133. {
  134. return ThreadState::allocator.deallocate(static_cast<ThreadState*>(ptr),
  135. 1);
  136. }
  137. static void init()
  138. {
  139. ThreadState::get_referrers_name = "get_referrers";
  140. ThreadState::set_clocks_used_doing_gc(0);
  141. }
  142. ThreadState()
  143. {
  144. #ifdef GREENLET_NEEDS_EXCEPTION_STATE_SAVED
  145. this->exception_state = slp_get_exception_state();
  146. #endif
  147. // XXX: Potentially dangerous, exposing a not fully
  148. // constructed object.
  149. MainGreenlet* const main = this->alloc_main();
  150. this->main_greenlet = OwnedMainGreenlet::consuming(
  151. main->self()
  152. );
  153. assert(this->main_greenlet);
  154. this->current_greenlet = main->self();
  155. // The main greenlet starts with 1 refs: The returned one. We
  156. // then copied it to the current greenlet.
  157. assert(this->main_greenlet.REFCNT() == 2);
  158. }
  159. inline void restore_exception_state()
  160. {
  161. #ifdef GREENLET_NEEDS_EXCEPTION_STATE_SAVED
  162. // It's probably important this be inlined and only call C
  163. // functions to avoid adding an SEH frame.
  164. slp_set_exception_state(this->exception_state);
  165. #endif
  166. }
  167. inline bool has_main_greenlet() const noexcept
  168. {
  169. return bool(this->main_greenlet);
  170. }
  171. // Called from the ThreadStateCreator when we're in non-standard
  172. // threading mode. In that case, there is an object in the Python
  173. // thread state dictionary that points to us. The main greenlet
  174. // also traverses into us, in which case it's crucial not to
  175. // traverse back into the main greenlet.
  176. int tp_traverse(visitproc visit, void* arg, bool traverse_main=true)
  177. {
  178. if (traverse_main) {
  179. Py_VISIT(main_greenlet.borrow_o());
  180. }
  181. if (traverse_main || current_greenlet != main_greenlet) {
  182. Py_VISIT(current_greenlet.borrow_o());
  183. }
  184. Py_VISIT(tracefunc.borrow());
  185. return 0;
  186. }
  187. inline BorrowedMainGreenlet borrow_main_greenlet() const noexcept
  188. {
  189. assert(this->main_greenlet);
  190. assert(this->main_greenlet.REFCNT() >= 2);
  191. return this->main_greenlet;
  192. };
  193. inline OwnedMainGreenlet get_main_greenlet() const noexcept
  194. {
  195. return this->main_greenlet;
  196. }
  197. /**
  198. * In addition to returning a new reference to the currunt
  199. * greenlet, this performs any maintenance needed.
  200. */
  201. inline OwnedGreenlet get_current()
  202. {
  203. /* green_dealloc() cannot delete greenlets from other threads, so
  204. it stores them in the thread dict; delete them now. */
  205. this->clear_deleteme_list();
  206. //assert(this->current_greenlet->main_greenlet == this->main_greenlet);
  207. //assert(this->main_greenlet->main_greenlet == this->main_greenlet);
  208. return this->current_greenlet;
  209. }
  210. /**
  211. * As for non-const get_current();
  212. */
  213. inline BorrowedGreenlet borrow_current()
  214. {
  215. this->clear_deleteme_list();
  216. return this->current_greenlet;
  217. }
  218. /**
  219. * Does no maintenance.
  220. */
  221. inline OwnedGreenlet get_current() const
  222. {
  223. return this->current_greenlet;
  224. }
  225. template<typename T, refs::TypeChecker TC>
  226. inline bool is_current(const refs::PyObjectPointer<T, TC>& obj) const
  227. {
  228. return this->current_greenlet.borrow_o() == obj.borrow_o();
  229. }
  230. inline void set_current(const OwnedGreenlet& target)
  231. {
  232. this->current_greenlet = target;
  233. }
  234. private:
  235. /**
  236. * Deref and remove the greenlets from the deleteme list. Must be
  237. * holding the GIL.
  238. *
  239. * If *murder* is true, then we must be called from a different
  240. * thread than the one that these greenlets were running in.
  241. * In that case, if the greenlet was actually running, we destroy
  242. * the frame reference and otherwise make it appear dead before
  243. * proceeding; otherwise, we would try (and fail) to raise an
  244. * exception in it and wind up right back in this list.
  245. */
  246. inline void clear_deleteme_list(const bool murder=false)
  247. {
  248. if (!this->deleteme.empty()) {
  249. // It's possible we could add items to this list while
  250. // running Python code if there's a thread switch, so we
  251. // need to defensively copy it before that can happen.
  252. deleteme_t copy = this->deleteme;
  253. this->deleteme.clear(); // in case things come back on the list
  254. for(deleteme_t::iterator it = copy.begin(), end = copy.end();
  255. it != end;
  256. ++it ) {
  257. PyGreenlet* to_del = *it;
  258. if (murder) {
  259. // Force each greenlet to appear dead; we can't raise an
  260. // exception into it anymore anyway.
  261. to_del->pimpl->murder_in_place();
  262. }
  263. // The only reference to these greenlets should be in
  264. // this list, decreffing them should let them be
  265. // deleted again, triggering calls to green_dealloc()
  266. // in the correct thread (if we're not murdering).
  267. // This may run arbitrary Python code and switch
  268. // threads or greenlets!
  269. Py_DECREF(to_del);
  270. if (PyErr_Occurred()) {
  271. PyErr_WriteUnraisable(nullptr);
  272. PyErr_Clear();
  273. }
  274. }
  275. }
  276. }
  277. public:
  278. /**
  279. * Returns a new reference, or a false object.
  280. */
  281. inline OwnedObject get_tracefunc() const
  282. {
  283. return tracefunc;
  284. };
  285. inline void set_tracefunc(BorrowedObject tracefunc)
  286. {
  287. assert(tracefunc);
  288. if (tracefunc == BorrowedObject(Py_None)) {
  289. this->tracefunc.CLEAR();
  290. }
  291. else {
  292. this->tracefunc = tracefunc;
  293. }
  294. }
  295. /**
  296. * Given a reference to a greenlet that some other thread
  297. * attempted to delete (has a refcount of 0) store it for later
  298. * deletion when the thread this state belongs to is current.
  299. */
  300. inline void delete_when_thread_running(PyGreenlet* to_del)
  301. {
  302. Py_INCREF(to_del);
  303. this->deleteme.push_back(to_del);
  304. }
  305. /**
  306. * Set to std::clock_t(-1) to disable.
  307. */
  308. inline static std::clock_t clocks_used_doing_gc()
  309. {
  310. #ifdef Py_GIL_DISABLED
  311. return ThreadState::_clocks_used_doing_gc.load(std::memory_order_relaxed);
  312. #else
  313. return ThreadState::_clocks_used_doing_gc;
  314. #endif
  315. }
  316. inline static void set_clocks_used_doing_gc(std::clock_t value)
  317. {
  318. #ifdef Py_GIL_DISABLED
  319. ThreadState::_clocks_used_doing_gc.store(value, std::memory_order_relaxed);
  320. #else
  321. ThreadState::_clocks_used_doing_gc = value;
  322. #endif
  323. }
  324. inline static void add_clocks_used_doing_gc(std::clock_t value)
  325. {
  326. #ifdef Py_GIL_DISABLED
  327. ThreadState::_clocks_used_doing_gc.fetch_add(value, std::memory_order_relaxed);
  328. #else
  329. ThreadState::_clocks_used_doing_gc += value;
  330. #endif
  331. }
  332. ~ThreadState()
  333. {
  334. if (!PyInterpreterState_Head()) {
  335. // We shouldn't get here (our callers protect us)
  336. // but if we do, all we can do is bail early.
  337. return;
  338. }
  339. // During interpreter finalization, Python APIs like
  340. // PyImport_ImportModule are unsafe (the import machinery may
  341. // be partially torn down). On Python < 3.11, perform only the
  342. // minimal cleanup that is safe: clear our strong references so
  343. // we don't leak, but skip the GC-based leak detection.
  344. //
  345. // Python 3.11+ restructured interpreter finalization so that
  346. // these APIs remain safe during shutdown.
  347. #if !GREENLET_PY311
  348. if (_Py_IsFinalizing()) {
  349. this->tracefunc.CLEAR();
  350. if (this->current_greenlet) {
  351. this->current_greenlet->murder_in_place();
  352. this->current_greenlet.CLEAR();
  353. }
  354. this->main_greenlet.CLEAR();
  355. return;
  356. }
  357. #endif
  358. // We should not have an "origin" greenlet; that only exists
  359. // for the temporary time during a switch, which should not
  360. // be in progress as the thread dies.
  361. //assert(!this->switching_state.origin);
  362. this->tracefunc.CLEAR();
  363. // Forcibly GC as much as we can.
  364. this->clear_deleteme_list(true);
  365. // The pending call did this.
  366. assert(this->main_greenlet->thread_state() == nullptr);
  367. // If the main greenlet is the current greenlet,
  368. // then we "fell off the end" and the thread died.
  369. // It's possible that there is some other greenlet that
  370. // switched to us, leaving a reference to the main greenlet
  371. // on the stack, somewhere uncollectible. Try to detect that.
  372. if (this->current_greenlet == this->main_greenlet && this->current_greenlet) {
  373. assert(this->current_greenlet->is_currently_running_in_some_thread());
  374. // Drop one reference we hold.
  375. this->current_greenlet.CLEAR();
  376. assert(!this->current_greenlet);
  377. // Only our reference to the main greenlet should be left,
  378. // But hold onto the pointer in case we need to do extra cleanup.
  379. PyGreenlet* old_main_greenlet = this->main_greenlet.borrow();
  380. Py_ssize_t cnt = this->main_greenlet.REFCNT();
  381. this->main_greenlet.CLEAR();
  382. if (ThreadState::clocks_used_doing_gc() != std::clock_t(-1)
  383. && cnt == 2 && Py_REFCNT(old_main_greenlet) == 1) {
  384. // Highly likely that the reference is somewhere on
  385. // the stack, not reachable by GC. Verify.
  386. // XXX: This is O(n) in the total number of objects.
  387. // TODO: Add a way to disable this at runtime, and
  388. // another way to report on it.
  389. std::clock_t begin = std::clock();
  390. NewReference gc(PyImport_ImportModule("gc"));
  391. if (gc) {
  392. OwnedObject get_referrers = gc.PyRequireAttr(ThreadState::get_referrers_name);
  393. OwnedList refs(get_referrers.PyCall(old_main_greenlet));
  394. if (refs && refs.empty()) {
  395. assert(refs.REFCNT() == 1);
  396. // We found nothing! So we left a dangling
  397. // reference: Probably the last thing some
  398. // other greenlet did was call
  399. // 'getcurrent().parent.switch()' to switch
  400. // back to us. Clean it up. This will be the
  401. // case on CPython 3.7 and newer, as they use
  402. // an internal calling conversion that avoids
  403. // creating method objects and storing them on
  404. // the stack.
  405. Py_DECREF(old_main_greenlet);
  406. }
  407. else if (refs
  408. && refs.size() == 1
  409. && PyCFunction_Check(refs.at(0))
  410. && Py_REFCNT(refs.at(0)) == 2) {
  411. assert(refs.REFCNT() == 1);
  412. // Ok, we found a C method that refers to the
  413. // main greenlet, and its only referenced
  414. // twice, once in the list we just created,
  415. // once from...somewhere else. If we can't
  416. // find where else, then this is a leak.
  417. // This happens in older versions of CPython
  418. // that create a bound method object somewhere
  419. // on the stack that we'll never get back to.
  420. if (PyCFunction_GetFunction(refs.at(0).borrow()) == (PyCFunction)green_switch) {
  421. BorrowedObject function_w = refs.at(0);
  422. refs.clear(); // destroy the reference
  423. // from the list.
  424. // back to one reference. Can *it* be
  425. // found?
  426. assert(function_w.REFCNT() == 1);
  427. refs = get_referrers.PyCall(function_w);
  428. if (refs && refs.empty()) {
  429. // Nope, it can't be found so it won't
  430. // ever be GC'd. Drop it.
  431. Py_CLEAR(function_w);
  432. }
  433. }
  434. }
  435. std::clock_t end = std::clock();
  436. ThreadState::add_clocks_used_doing_gc(end - begin);
  437. }
  438. }
  439. }
  440. // We need to make sure this greenlet appears to be dead,
  441. // because otherwise deallocing it would fail to raise an
  442. // exception in it (the thread is dead) and put it back in our
  443. // deleteme list.
  444. if (this->current_greenlet) {
  445. this->current_greenlet->murder_in_place();
  446. this->current_greenlet.CLEAR();
  447. }
  448. if (this->main_greenlet) {
  449. // Couldn't have been the main greenlet that was running
  450. // when the thread exited (because we already cleared this
  451. // pointer if it was). This shouldn't be possible?
  452. // If the main greenlet was current when the thread died (it
  453. // should be, right?) then we cleared its self pointer above
  454. // when we cleared the current greenlet's main greenlet pointer.
  455. // assert(this->main_greenlet->main_greenlet == this->main_greenlet
  456. // || !this->main_greenlet->main_greenlet);
  457. // // self reference, probably gone
  458. // this->main_greenlet->main_greenlet.CLEAR();
  459. // This will actually go away when the ivar is destructed.
  460. this->main_greenlet.CLEAR();
  461. }
  462. if (PyErr_Occurred()) {
  463. PyErr_WriteUnraisable(NULL);
  464. PyErr_Clear();
  465. }
  466. }
  467. };
  468. ImmortalString ThreadState::get_referrers_name(nullptr);
  469. PythonAllocator<ThreadState> ThreadState::allocator;
  470. #ifdef Py_GIL_DISABLED
  471. std::atomic<std::clock_t> ThreadState::_clocks_used_doing_gc(0);
  472. #else
  473. std::clock_t ThreadState::_clocks_used_doing_gc(0);
  474. #endif
  475. }; // namespace greenlet
  476. #endif