TUserGreenlet.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662
  1. /* -*- indent-tabs-mode: nil; tab-width: 4; -*- */
  2. /**
  3. * Implementation of greenlet::UserGreenlet.
  4. *
  5. * Format with:
  6. * clang-format -i --style=file src/greenlet/greenlet.c
  7. *
  8. *
  9. * Fix missing braces with:
  10. * clang-tidy src/greenlet/greenlet.c -fix -checks="readability-braces-around-statements"
  11. */
  12. #ifndef T_USER_GREENLET_CPP
  13. #define T_USER_GREENLET_CPP
  14. #include "greenlet_internal.hpp"
  15. #include "TGreenlet.hpp"
  16. #include "TThreadStateDestroy.cpp"
  17. namespace greenlet {
  18. using greenlet::refs::BorrowedMainGreenlet;
  19. greenlet::PythonAllocator<UserGreenlet> UserGreenlet::allocator;
  20. void* UserGreenlet::operator new(size_t UNUSED(count))
  21. {
  22. return allocator.allocate(1);
  23. }
  24. void UserGreenlet::operator delete(void* ptr)
  25. {
  26. return allocator.deallocate(static_cast<UserGreenlet*>(ptr),
  27. 1);
  28. }
  29. UserGreenlet::UserGreenlet(PyGreenlet* p, BorrowedGreenlet the_parent)
  30. : Greenlet(p), _parent(the_parent)
  31. {
  32. }
  33. UserGreenlet::~UserGreenlet()
  34. {
  35. // Python 3.11: If we don't clear out the raw frame datastack
  36. // when deleting an unfinished greenlet,
  37. // TestLeaks.test_untracked_memory_doesnt_increase_unfinished_thread_dealloc_in_main fails.
  38. this->python_state.did_finish(nullptr);
  39. this->tp_clear();
  40. }
  41. const BorrowedMainGreenlet
  42. UserGreenlet::main_greenlet() const
  43. {
  44. return this->_main_greenlet;
  45. }
  46. BorrowedMainGreenlet
  47. UserGreenlet::find_main_greenlet_in_lineage() const
  48. {
  49. if (this->started()) {
  50. assert(this->_main_greenlet);
  51. return BorrowedMainGreenlet(this->_main_greenlet);
  52. }
  53. if (!this->_parent) {
  54. /* garbage collected greenlet in chain */
  55. // XXX: WHAT?
  56. return BorrowedMainGreenlet(nullptr);
  57. }
  58. return this->_parent->find_main_greenlet_in_lineage();
  59. }
  60. /**
  61. * CAUTION: This will allocate memory and may trigger garbage
  62. * collection and arbitrary Python code.
  63. */
  64. OwnedObject
  65. UserGreenlet::throw_GreenletExit_during_dealloc(const ThreadState& current_thread_state)
  66. {
  67. /* The dying greenlet cannot be a parent of ts_current
  68. because the 'parent' field chain would hold a
  69. reference */
  70. UserGreenlet::ParentIsCurrentGuard with_current_parent(this, current_thread_state);
  71. // We don't care about the return value, only whether an
  72. // exception happened. Whether or not an exception happens,
  73. // we need to restore the parent in case the greenlet gets
  74. // resurrected.
  75. return Greenlet::throw_GreenletExit_during_dealloc(current_thread_state);
  76. }
  77. ThreadState*
  78. UserGreenlet::thread_state() const noexcept
  79. {
  80. // TODO: maybe make this throw, if the thread state isn't there?
  81. // if (!this->main_greenlet) {
  82. // throw std::runtime_error("No thread state"); // TODO: Better exception
  83. // }
  84. if (!this->_main_greenlet) {
  85. return nullptr;
  86. }
  87. return this->_main_greenlet->thread_state();
  88. }
  89. bool
  90. UserGreenlet::was_running_in_dead_thread() const noexcept
  91. {
  92. return this->_main_greenlet && !this->thread_state();
  93. }
  94. OwnedObject
  95. UserGreenlet::g_switch()
  96. {
  97. assert(this->args() || PyErr_Occurred());
  98. try {
  99. this->check_switch_allowed();
  100. }
  101. catch (const PyErrOccurred&) {
  102. this->release_args();
  103. throw;
  104. }
  105. // Switching greenlets used to attempt to clean out ones that need
  106. // deleted *if* we detected a thread switch. Should it still do
  107. // that?
  108. // An issue is that if we delete a greenlet from another thread,
  109. // it gets queued to this thread, and ``kill_greenlet()`` switches
  110. // back into the greenlet
  111. /* find the real target by ignoring dead greenlets,
  112. and if necessary starting a greenlet. */
  113. switchstack_result_t err;
  114. Greenlet* target = this;
  115. // TODO: probably cleaner to handle the case where we do
  116. // switch to ourself separately from the other cases.
  117. // This can probably even further be simplified if we keep
  118. // track of the switching_state we're going for and just call
  119. // into g_switch() if it's not ourself. The main problem with that
  120. // is that we would be using more stack space.
  121. bool target_was_me = true;
  122. bool was_initial_stub = false;
  123. while (target) {
  124. if (target->active()) {
  125. if (!target_was_me) {
  126. target->args() <<= this->args();
  127. assert(!this->args());
  128. }
  129. err = target->g_switchstack();
  130. break;
  131. }
  132. if (!target->started()) {
  133. // We never encounter a main greenlet that's not started.
  134. assert(!target->main());
  135. UserGreenlet* real_target = static_cast<UserGreenlet*>(target);
  136. assert(real_target);
  137. void* dummymarker;
  138. was_initial_stub = true;
  139. if (!target_was_me) {
  140. target->args() <<= this->args();
  141. assert(!this->args());
  142. }
  143. try {
  144. // This can only throw back to us while we're
  145. // still in this greenlet. Once the new greenlet
  146. // is bootstrapped, it has its own exception state.
  147. err = real_target->g_initialstub(&dummymarker);
  148. }
  149. catch (const PyErrOccurred&) {
  150. this->release_args();
  151. throw;
  152. }
  153. catch (const GreenletStartedWhileInPython&) {
  154. // The greenlet was started sometime before this
  155. // greenlet actually switched to it, i.e.,
  156. // "concurrent" calls to switch() or throw().
  157. // We need to retry the switch.
  158. // Note that the current greenlet has been reset
  159. // to this one (or we wouldn't be running!)
  160. continue;
  161. }
  162. break;
  163. }
  164. target = target->parent();
  165. target_was_me = false;
  166. }
  167. // The ``this`` pointer and all other stack or register based
  168. // variables are invalid now, at least where things succeed
  169. // above.
  170. // But this one, probably not so much? It's not clear if it's
  171. // safe to throw an exception at this point.
  172. if (err.status < 0) {
  173. // If we get here, either g_initialstub()
  174. // failed, or g_switchstack() failed. Either one of those
  175. // cases SHOULD leave us in the original greenlet with a valid
  176. // stack.
  177. return this->on_switchstack_or_initialstub_failure(target, err, target_was_me, was_initial_stub);
  178. }
  179. // err.the_new_current_greenlet would be the same as ``target``,
  180. // if target wasn't probably corrupt.
  181. return err.the_new_current_greenlet->g_switch_finish(err);
  182. }
  183. Greenlet::switchstack_result_t
  184. UserGreenlet::g_initialstub(void* mark)
  185. {
  186. OwnedObject run;
  187. // We need to grab a reference to the current switch arguments
  188. // in case we're entered concurrently during the call to
  189. // GetAttr() and have to try again.
  190. // We'll restore them when we return in that case.
  191. // Scope them tightly to avoid ref leaks.
  192. {
  193. SwitchingArgs args(this->args());
  194. /* save exception in case getattr clears it */
  195. PyErrPieces saved;
  196. /*
  197. self.run is the object to call in the new greenlet.
  198. This could run arbitrary python code and switch greenlets!
  199. */
  200. run = this->self().PyRequireAttr(mod_globs->str_run);
  201. /* restore saved exception */
  202. saved.PyErrRestore();
  203. /* recheck that it's safe to switch in case greenlet reparented anywhere above */
  204. this->check_switch_allowed();
  205. /* by the time we got here another start could happen elsewhere,
  206. * that means it should now be a regular switch.
  207. * This can happen if the Python code is a subclass that implements
  208. * __getattribute__ or __getattr__, or makes ``run`` a descriptor;
  209. * all of those can run arbitrary code that switches back into
  210. * this greenlet.
  211. */
  212. if (this->stack_state.started()) {
  213. // the successful switch cleared these out, we need to
  214. // restore our version. They will be copied on up to the
  215. // next target.
  216. assert(!this->args());
  217. this->args() <<= args;
  218. throw GreenletStartedWhileInPython();
  219. }
  220. }
  221. // Sweet, if we got here, we have the go-ahead and will switch
  222. // greenlets.
  223. // Nothing we do from here on out should allow for a thread or
  224. // greenlet switch: No arbitrary calls to Python, including
  225. // decref'ing
  226. #if GREENLET_USE_CFRAME
  227. /* OK, we need it, we're about to switch greenlets, save the state. */
  228. /*
  229. See green_new(). This is a stack-allocated variable used
  230. while *self* is in PyObject_Call().
  231. We want to defer copying the state info until we're sure
  232. we need it and are in a stable place to do so.
  233. */
  234. _PyCFrame trace_info;
  235. this->python_state.set_new_cframe(trace_info);
  236. #endif
  237. /* start the greenlet */
  238. ThreadState& thread_state = GET_THREAD_STATE().state();
  239. this->stack_state = StackState(mark,
  240. thread_state.borrow_current()->stack_state);
  241. this->python_state.set_initial_state(PyThreadState_GET());
  242. this->exception_state.clear();
  243. this->_main_greenlet = thread_state.get_main_greenlet();
  244. /* perform the initial switch */
  245. switchstack_result_t err = this->g_switchstack();
  246. /* returns twice!
  247. The 1st time with ``err == 1``: we are in the new greenlet.
  248. This one owns a greenlet that used to be current.
  249. The 2nd time with ``err <= 0``: back in the caller's
  250. greenlet; this happens if the child finishes or switches
  251. explicitly to us. Either way, the ``err`` variable is
  252. created twice at the same memory location, but possibly
  253. having different ``origin`` values. Note that it's not
  254. constructed for the second time until the switch actually happens.
  255. */
  256. if (err.status == 1) {
  257. // In the new greenlet.
  258. // This never returns! Calling inner_bootstrap steals
  259. // the contents of our run object within this stack frame, so
  260. // it is not valid to do anything with it.
  261. try {
  262. this->inner_bootstrap(err.origin_greenlet.relinquish_ownership(),
  263. run.relinquish_ownership());
  264. }
  265. // Getting a C++ exception here isn't good. It's probably a
  266. // bug in the underlying greenlet, meaning it's probably a
  267. // C++ extension. We're going to abort anyway, but try to
  268. // display some nice information *if* possible. Some obscure
  269. // platforms don't properly support this (old 32-bit Arm, see see
  270. // https://github.com/python-greenlet/greenlet/issues/385); that's not
  271. // great, but should usually be OK because, as mentioned above, we're
  272. // terminating anyway.
  273. //
  274. // The catching is tested by
  275. // ``test_cpp.CPPTests.test_unhandled_exception_in_greenlet_aborts``.
  276. //
  277. // PyErrOccurred can theoretically be thrown by
  278. // inner_bootstrap() -> g_switch_finish(), but that should
  279. // never make it back to here. It is a std::exception and
  280. // would be caught if it is.
  281. catch (const std::exception& e) {
  282. std::string base = "greenlet: Unhandled C++ exception: ";
  283. base += e.what();
  284. Py_FatalError(base.c_str());
  285. }
  286. catch (...) {
  287. // Some compilers/runtimes use exceptions internally.
  288. // It appears that GCC on Linux with libstdc++ throws an
  289. // exception internally at process shutdown time to unwind
  290. // stacks and clean up resources. Depending on exactly
  291. // where we are when the process exits, that could result
  292. // in an unknown exception getting here. If we
  293. // Py_FatalError() or abort() here, we interfere with
  294. // orderly process shutdown. Throwing the exception on up
  295. // is the right thing to do.
  296. //
  297. // gevent's ``examples/dns_mass_resolve.py`` demonstrates this.
  298. #ifndef NDEBUG
  299. fprintf(stderr,
  300. "greenlet: inner_bootstrap threw unknown exception; "
  301. "is the process terminating?\n");
  302. #endif
  303. throw;
  304. }
  305. Py_FatalError("greenlet: inner_bootstrap returned with no exception.\n");
  306. }
  307. // In contrast, notice that we're keeping the origin greenlet
  308. // around as an owned reference; we need it to call the trace
  309. // function for the switch back into the parent. It was only
  310. // captured at the time the switch actually happened, though,
  311. // so we haven't been keeping an extra reference around this
  312. // whole time.
  313. /* back in the parent */
  314. if (err.status < 0) {
  315. /* start failed badly, restore greenlet state */
  316. this->stack_state = StackState();
  317. this->_main_greenlet.CLEAR();
  318. // CAUTION: This may run arbitrary Python code.
  319. run.CLEAR(); // inner_bootstrap didn't run, we own the reference.
  320. }
  321. // In the success case, the spawned code (inner_bootstrap) will
  322. // take care of decrefing this, so we relinquish ownership so as
  323. // to not double-decref.
  324. run.relinquish_ownership();
  325. return err;
  326. }
  327. void
  328. UserGreenlet::inner_bootstrap(PyGreenlet* origin_greenlet, PyObject* run)
  329. {
  330. // The arguments here would be another great place for move.
  331. // As it is, we take them as a reference so that when we clear
  332. // them we clear what's on the stack above us. Do that NOW, and
  333. // without using a C++ RAII object,
  334. // so there's no way that exiting the parent frame can clear it,
  335. // or we clear it unexpectedly. This arises in the context of the
  336. // interpreter shutting down. See https://github.com/python-greenlet/greenlet/issues/325
  337. //PyObject* run = _run.relinquish_ownership();
  338. /* in the new greenlet */
  339. assert(this->thread_state()->borrow_current() == BorrowedGreenlet(this->_self));
  340. // C++ exceptions cannot propagate to the parent greenlet from
  341. // here. (TODO: Do we need a catch(...) clause, perhaps on the
  342. // function itself? ALl we could do is terminate the program.)
  343. // NOTE: On 32-bit Windows, the call chain is extremely
  344. // important here in ways that are subtle, having to do with
  345. // the depth of the SEH list. The call to restore it MUST NOT
  346. // add a new SEH handler to the list, or we'll restore it to
  347. // the wrong thing.
  348. this->thread_state()->restore_exception_state();
  349. /* stack variables from above are no good and also will not unwind! */
  350. // EXCEPT: That can't be true, we access run, among others, here.
  351. this->stack_state.set_active(); /* running */
  352. // We're about to possibly run Python code again, which
  353. // could switch back/away to/from us, so we need to grab the
  354. // arguments locally.
  355. SwitchingArgs args;
  356. args <<= this->args();
  357. assert(!this->args());
  358. // XXX: We could clear this much earlier, right?
  359. // Or would that introduce the possibility of running Python
  360. // code when we don't want to?
  361. // CAUTION: This may run arbitrary Python code.
  362. this->_run_callable.CLEAR();
  363. // The first switch we need to manually call the trace
  364. // function here instead of in g_switch_finish, because we
  365. // never return there.
  366. if (OwnedObject tracefunc = this->thread_state()->get_tracefunc()) {
  367. OwnedGreenlet trace_origin;
  368. trace_origin = origin_greenlet;
  369. try {
  370. g_calltrace(tracefunc,
  371. args ? mod_globs->event_switch : mod_globs->event_throw,
  372. trace_origin,
  373. this->_self);
  374. }
  375. catch (const PyErrOccurred&) {
  376. /* Turn trace errors into switch throws */
  377. args.CLEAR();
  378. }
  379. }
  380. // We no longer need the origin, it was only here for
  381. // tracing.
  382. // We may never actually exit this stack frame so we need
  383. // to explicitly clear it.
  384. // This could run Python code and switch.
  385. Py_CLEAR(origin_greenlet);
  386. OwnedObject result;
  387. if (!args) {
  388. /* pending exception */
  389. result = NULL;
  390. }
  391. else {
  392. /* call g.run(*args, **kwargs) */
  393. // This could result in further switches
  394. try {
  395. //result = run.PyCall(args.args(), args.kwargs());
  396. // CAUTION: Just invoking this, before the function even
  397. // runs, may cause memory allocations, which may trigger
  398. // GC, which may run arbitrary Python code.
  399. result = OwnedObject::consuming(PyObject_Call(run, args.args().borrow(), args.kwargs().borrow()));
  400. }
  401. catch (...) {
  402. // Unhandled C++ exception!
  403. // If we declare ourselves as noexcept, if we don't catch
  404. // this here, most platforms will just abort() the
  405. // process. But on 64-bit Windows with older versions of
  406. // the C runtime, this can actually corrupt memory and
  407. // just return. We see this when compiling with the
  408. // Windows 7.0 SDK targeting Windows Server 2008, but not
  409. // when using the Appveyor Visual Studio 2019 image. So
  410. // this currently only affects Python 2.7 on Windows 64.
  411. // That is, the tests pass and the runtime aborts
  412. // everywhere else.
  413. //
  414. // However, if we catch it and try to continue with a
  415. // Python error, then all Windows 64 bit platforms corrupt
  416. // memory. So all we can do is manually abort, hopefully
  417. // with a good error message. (Note that the above was
  418. // tested WITHOUT the `/EHr` switch being used at compile
  419. // time, so MSVC may have "optimized" out important
  420. // checking. Using that switch, we may be in a better
  421. // place in terms of memory corruption.) But sometimes it
  422. // can't be caught here at all, which is confusing but not
  423. // terribly surprising; so again, the G_NOEXCEPT_WIN32
  424. // plus "/EHr".
  425. //
  426. // Hopefully the basic C stdlib is still functional enough
  427. // for us to at least print an error.
  428. //
  429. // It gets more complicated than that, though, on some
  430. // platforms, specifically at least Linux/gcc/libstdc++. They use
  431. // an exception to unwind the stack when a background
  432. // thread exits. (See comments about noexcept.) So this
  433. // may not actually represent anything untoward. On those
  434. // platforms we allow throws of this to propagate, or
  435. // attempt to anyway.
  436. # if defined(WIN32) || defined(_WIN32)
  437. Py_FatalError(
  438. "greenlet: Unhandled C++ exception from a greenlet run function. "
  439. "Because memory is likely corrupted, terminating process.");
  440. std::abort();
  441. #else
  442. throw;
  443. #endif
  444. }
  445. }
  446. // These lines may run arbitrary code
  447. args.CLEAR();
  448. Py_CLEAR(run);
  449. if (!result
  450. && mod_globs->PyExc_GreenletExit.PyExceptionMatches()
  451. && (this->args())) {
  452. // This can happen, for example, if our only reference
  453. // goes away after we switch back to the parent.
  454. // See test_dealloc_switch_args_not_lost
  455. PyErrPieces clear_error;
  456. result <<= this->args();
  457. result = single_result(result);
  458. }
  459. this->release_args();
  460. this->python_state.did_finish(PyThreadState_GET());
  461. result = g_handle_exit(result);
  462. assert(this->thread_state()->borrow_current() == this->_self);
  463. /* jump back to parent */
  464. this->stack_state.set_inactive(); /* dead */
  465. // TODO: Can we decref some things here? Release our main greenlet
  466. // and maybe parent?
  467. for (Greenlet* parent = this->_parent;
  468. parent;
  469. parent = parent->parent()) {
  470. // We need to somewhere consume a reference to
  471. // the result; in most cases we'll never have control
  472. // back in this stack frame again. Calling
  473. // green_switch actually adds another reference!
  474. // This would probably be clearer with a specific API
  475. // to hand results to the parent.
  476. parent->args() <<= result;
  477. assert(!result);
  478. // The parent greenlet now owns the result; in the
  479. // typical case we'll never get back here to assign to
  480. // result and thus release the reference.
  481. try {
  482. result = parent->g_switch();
  483. }
  484. catch (const PyErrOccurred&) {
  485. // Ignore, keep passing the error on up.
  486. }
  487. /* Return here means switch to parent failed,
  488. * in which case we throw *current* exception
  489. * to the next parent in chain.
  490. */
  491. assert(!result);
  492. }
  493. /* We ran out of parents, cannot continue */
  494. PyErr_WriteUnraisable(this->self().borrow_o());
  495. Py_FatalError("greenlet: ran out of parent greenlets while propagating exception; "
  496. "cannot continue");
  497. std::abort();
  498. }
  499. void
  500. UserGreenlet::run(const BorrowedObject nrun)
  501. {
  502. if (this->started()) {
  503. throw AttributeError(
  504. "run cannot be set "
  505. "after the start of the greenlet");
  506. }
  507. this->_run_callable = nrun;
  508. }
  509. const OwnedGreenlet
  510. UserGreenlet::parent() const
  511. {
  512. return this->_parent;
  513. }
  514. void
  515. UserGreenlet::parent(const BorrowedObject raw_new_parent)
  516. {
  517. if (!raw_new_parent) {
  518. throw AttributeError("can't delete attribute");
  519. }
  520. BorrowedMainGreenlet main_greenlet_of_new_parent;
  521. BorrowedGreenlet new_parent(raw_new_parent.borrow()); // could
  522. // throw
  523. // TypeError!
  524. for (BorrowedGreenlet p = new_parent; p; p = p->parent()) {
  525. if (p == this->self()) {
  526. throw ValueError("cyclic parent chain");
  527. }
  528. main_greenlet_of_new_parent = p->main_greenlet();
  529. }
  530. if (!main_greenlet_of_new_parent) {
  531. throw ValueError("parent must not be garbage collected");
  532. }
  533. if (this->started()
  534. && this->_main_greenlet != main_greenlet_of_new_parent) {
  535. throw ValueError("parent cannot be on a different thread");
  536. }
  537. this->_parent = new_parent;
  538. }
  539. void
  540. UserGreenlet::murder_in_place()
  541. {
  542. this->_main_greenlet.CLEAR();
  543. Greenlet::murder_in_place();
  544. }
  545. bool
  546. UserGreenlet::belongs_to_thread(const ThreadState* thread_state) const
  547. {
  548. return Greenlet::belongs_to_thread(thread_state) && this->_main_greenlet == thread_state->borrow_main_greenlet();
  549. }
  550. int
  551. UserGreenlet::tp_traverse(visitproc visit, void* arg)
  552. {
  553. Py_VISIT(this->_parent.borrow_o());
  554. Py_VISIT(this->_main_greenlet.borrow_o());
  555. Py_VISIT(this->_run_callable.borrow_o());
  556. return Greenlet::tp_traverse(visit, arg);
  557. }
  558. int
  559. UserGreenlet::tp_clear()
  560. {
  561. Greenlet::tp_clear();
  562. this->_parent.CLEAR();
  563. this->_main_greenlet.CLEAR();
  564. this->_run_callable.CLEAR();
  565. return 0;
  566. }
  567. UserGreenlet::ParentIsCurrentGuard::ParentIsCurrentGuard(UserGreenlet* p,
  568. const ThreadState& thread_state)
  569. : oldparent(p->_parent),
  570. greenlet(p)
  571. {
  572. p->_parent = thread_state.get_current();
  573. }
  574. UserGreenlet::ParentIsCurrentGuard::~ParentIsCurrentGuard()
  575. {
  576. this->greenlet->_parent = oldparent;
  577. oldparent.CLEAR();
  578. }
  579. }; //namespace greenlet
  580. #endif