....................................../////.===Hehe-Here===./////................................................ > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < ------------------------------------------------------------------------------------------------------------------- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// RIFF¤ WEBPVP8 ˜ ðÑ *ôô>‘HŸK¥¤"§£±¨àð enü¹%½_F‘åè¿2ºQú³íªú`N¿­3ÿƒügµJžaÿ¯ÿ°~¼ÎùnúîÞÖô•òíôÁÉß®Sm¥Ü/ ‡ó˜f£Ùà<˜„xëJ¢Ù€SO3x<ªÔ©4¿+ç¶A`q@Ì“Úñè™ÍÿJÌ´ª-˜ÆtÊÛL]Ïq*‘Ý”ì#ŸÌÏãY]@ê`¿ /ªfkØB4·®£ó z—Üw¥Pxù–ÞLШKÇN¾AkÙTf½è'‰g gÆv›Øuh~ a˜Z— ïj*á¥t d£“uÒ ¨`K˜¹ßþ]b>˜]_ÏÔ6W—è2r4x•íÖ…"ƒÖNîä!¦å Ú}ýxGøÌ —@ ;ÆÚŠ=ɾ1ý8lªË¥ô ^yf®Œ¢u&2©nÙÇ›ñÂñŒ³ aPo['½»øFùà­+4ê“$!lövlüÞ=;N®3ð‚õ›DÉKòÞ>ÄÍ ¥ˆuߤ#ˆ$6ù™¥îЇy’ÍB¼ çxÛ;X"WL£R÷͝*ó-¶Zu}º.s¸sšXqù–DþÿvªhüïwyŸ ¯é³lÀ:KCûÄ£Ëá\…­ ~—ýóî ¼ûûÜTÓüÇy…ŽÆvc»¾×U ñ¸žþоP÷¦ó:Ò¨¨5;Ð#&#ÖúñläÿÁœ GxÉ­/ñ‡áQðìYÉtÒw޼GÔ´zàÒò ð*ëzƒ•4~H]Ø‹f ñÓÈñ`NåWçs'ÆÏW^ø¹!XžµmQ5ÃËoLœÎ: ÞËÍ¥J ù…î èo£ßPÎñ¶ž8.Œ]ʵ~5›ÙË-ù*8ÙÖß±~ ©¹rÓê‚j¶d¸{^Q'˜±Crß ÚH—#¥¥QlÀ×ëã‡DÜ«èî þ&Çæžî;ŽÏºò6ÒLÃXy&ZŒ'j‚¢Ù€IßÚù+–MGi‰*jE€‘JcÜ ÓÌ EÏÚj]o˜ Þr <¾U ûŪæÍ/šÝH¥˜b”¼ ÁñßX GP›ï2›4WŠÏà×£…íÓk†¦H·ÅíMh–*nó÷à]ÁjCº€b7<ب‹¨5車bp2:Á[UªM„QŒçiNMa#<5›áËó¸HýÊ"…×Éw¹¦ì2º–x<›»a±¸3Weü®FÝ⑱ö–î–³|LPÈ~çð~Çå‡|º kD¢µÏàÆAI %1À% ¹Ò – ”ϝS¦‰4&¶£°à Öý”û_Ò Áw°A«Å€?mÇÛgHÉ/8)á¾ÛìáöŽP í¨PŸNÙµº¦‡§Ùš"ÿ«>+ªÕ`Ê÷‡‚ß Õû˜þãÇ-PÍ.¾XV‘€ dÜ"þ4¹ ±Oú‘©t¥¦FªÄÃÄ•b‚znýu½—#cDs˜ÃiÑOˆñ×QO=*IAÊ,¶ŽZƒ;‡wøXè%EÐk:F±Ú” .Ѽ+Áu&Ç`."pÈÉw o&¿dE6‘’EqTuK@Ì¥ã™À(Êk(h‰,H}RÀIXÛš3µ1©_OqÚÒJAñ$ÊÙÜ;D3çŒ[þùœh¬Ã³™ö6ç†NY".Ú‰ï[ªŸŒ '²Ð öø_¨ÂÉ9ué¶³ÒŠõTàîMØ#û¯gN‡bÙ놚X„ö …ÉeüÌ^J ‹€.œ$Æ)βÄeæW#óüßĺŸ€ ÀzwV 9oä»f4V*uB «Ë†¹ì¯žR霓æHXa=&“I4K;¯ç‹h×·"UŠ~<•╪Vêª&ÍSÃÆÅ?ÔqÎ*mTM ˜›µwêd#[C¡©§‘D<©àb†–ÁœøvH/,í:¯( ²£|4-„Æövv„Yͼ™^Á$ˆ„¢Û[6yB.åH*V¨æ?$=˜Ñ€•ñ·­(VlŸ‘ nÀt8W÷´Bûba?q9ú¶Xƒl«ÿ\ù¶’þòUÐj/õ¢Ìµ³g$ƒÎR!¸»|Oߍë’BhîÚÑ¢ñåŒJ„®„£2Ð3•ô02Nt…!£Í]Ïc½Qÿ?ˆ<&ÃA¾Ú,JˆijÌ#5yz„‰Î|ÊŽ5QÏ:‹ÐaóVÔxW—CpeÏzÐïíçôÿÅ_[hãsÐ_/ŽTÝ?BîˆííV$<¿i>²F¬_Eß¿ †bÊŒº­ÿ®Z H“C}”¬,Mp ý/Bá£w>˜YV°aƒúh+cŠ- r/[%|üUMHäQ°X»|û/@|°¥Ð !BÔ Ç¢Ä©š+Õì D«7ìN¶ŽðÔ " ƶ’ÖçtA‰Û×}{tþz­¾GÍ›k¹OEJR$ Â׃ «ëÁ"oÉôž$oUK(Ä)Ãz³Ê-‹êN[Ò3Œñbï8P 4ƒ×q¢bo|?<ÛX¬òÄͰL–±›(™ûG?ýË©ÚÄ–ÂDØÐ_Ç¡ô ¾–ÄÏø ×e8Ë©$ÄF¹Å‹ì[©óìl:F¾f´‹‹Xì²ï®\¬ôùƒ ÿat¥óèÒùHß0äe‚;ü×h:ÆWðHž=Ã8骣"kœ'Y?³}Tûè€>?0l›e1Lòñ„aæKÆw…hÖŠùW…ÈÆÄ0ši·›[pcwËþñiêíY/~-Á5˜!¿†A›™Mÿþ(±“t@â“ö2­´TG5yé]çå僳 .·ÍïçÝ7UÚ±Ð/Nè»,_Ï ùdj7\ï Wì4›„»c¸àešg#ÒÊ⥭áØo5‘?ÌdÝô¯ ¹kzsƒ=´#ëÉK›Ø´±-¥eW?‡çßtòTã…$Ý+qÿ±ƒ÷_3Ô¥í÷:æ–ž<·Ö‡‰Å¢ š‡%Ô—utÌÈìðžgÖÀz²À—ï÷Óîäõ{K'´È÷³yaÏÁjƒô}ž§®æÊydÕÈë5¯èˆõvÕ©ã*çD„ “z„Ó‡^^xÂ3M§A´JG‚öï 3W'ˆ.OvXè¡ÊÕª?5º7†˜(˜Ç¶#çê’¶!ÌdZK§æ 0fãaN]òY³RV ™î$®K2R¨`W!1Ôó\;Ý ýB%qæK•&ÓÈe9È0êI±žeŸß -ú@žQr¦ ö4»M¼Áè¹µmw 9 EÆE_°2ó„ŸXKWÁ×Hóì^´²GѝF©óäR†¦‰ç"V»eØ<3ùd3ÿÚ¤Žú“Gi" —‘_ÙËÎ~Üö¯¥½Î»üŸEÚŽåmÞþí ;ÞólËΦMzA"Âf(´òá;Éï(/7½ûñÌ­cïÕçлþÝz¾-ÍvÑ“pH­–ðÓj$¸Äû¤‚‘ãUBË-n“2åPkS5&‹Â|+g^œ®Ì͆d!OïäîU«c;{Û!ÅŽ«ëZ9Ókóˆ]¯ƒ›né `ÇÒ+tÆš (ØKá¾—=3œ®•vuMñg²\ï Ec€ 05±d™‡×iÇ×›UúvÌ¢£Èþ¡ÕØô¶ßÎA"ß±#Ö²ˆÊŸ¦*Ä~ij|àø.-¼'»Ú¥£h ofº¦‡VsR=N½„Î v˜Z*SÌ{=jÑB‹tê…;’HžH¯8–îDù8ñ¢|Q•bÛçš–‹m³“ê¨ åÏ^m¬Žãþ©ïêO‡½6] µÆ„Ooòü ²x}N¦Ë3ïé¿»€›HA˜m%çÞ/¿í7Fø“‹léUk)É°Œµ8Q8›:ÀŠeT*šõ~ôڝG6 ¢}`ùH­–”¡k ‰P1>š†®9z11!X wKfmÁ¦xÑ,N1Q”–æB¶M…ÒÃv6SMˆhU¬ÊPŽï‘öj=·CŒ¯u¹ƒVIЃsx4’ömÛýcå¡¶7ßŠß 57^\wÒÐÆ k§h,Œý î«q^R½3]J¸ÇðN ‚çU¬ôº^Áì} ³f©Õœ§ˆã:FÄÈ‚é(€™?àýÓüè1Gô£¼éj‚OÅñ  #>×—ßtà 0G¥Åa뀐kßhc™À_ÉñÞ#±)GD" YîäË-ÿÙ̪ ¹™a¯´¢E\ÝÒö‚;™„ë]_ p8‰o¡ñ+^÷ 3‘'dT4œŽ ðVë½° :¬víÑ«£tßÚS-3¶“þ2 †üüʨòrš¹M{É_¤`Û¨0ìjœøJ‡:÷ÃáZ˜†@GP&œÑDGÏs¡þ¦þDGú‘1Yá9Ôþ¼ ûø…§÷8&–ÜÑnÄ_m®^üÆ`;ÉVÁJ£?â€-ßê}suÍ2sõA NÌúA磸‘îÿÚ»ƒìö·á¿±tÑÐ"Tÿü˜[@/äj¬€uüªìù¥Ý˜á8Ý´sõj 8@rˆð äþZÇD®ÿUÏ2ùôõrBzÆÏÞž>Ì™xœ“ wiÎ×7_… ¸ \#€MɁV¶¥üÕÿPÔ9Z‡ø§É8#H:ƒ5ÀÝå9ÍIŒ5åKÙŠ÷qÄ>1AÈøžj"µÂд/ªnÀ qªã}"iŸBå˜ÓÛŽ¦…&ݧ;G@—³b¯“•"´4í¨ôM¨åñC‹ïùÉó¯ÓsSH2Ý@ßáM‡ˆKÀªÛUeø/4\gnm¥‹ŸŒ qÄ b9ÞwÒNÏ_4Ég³ú=܆‚´ •â¥õeíþkjz>éÚyU«Íӝ݃6"8/ø{=Ô¢»G¥ äUw°W«,ô—¿ãㆅү¢³xŠUû™yŒ (øSópÐ 9\åTâ»—*oG$/×ÍT†Y¿1¤Þ¢_‡ ¼ „±ÍçèSaÓ 3ÛMÁBkxs‰’R/¡¤ˆÙçª(*õ„üXÌ´ƒ E§´¬EF"Ù”R/ÐNyÆÂ^°?™6¡œïJ·±$§?º>ÖüœcNÌù¯G ‹ñ2ЁBB„^·úìaz¨k:#¨Æ¨8LÎõލ£^§S&cŒÐU€ü(‡F±Š¼&P>8ÙÁ ‰ p5?0ÊÆƒZl¸aô š¼¡}gÿ¶zÆC²¹¬ÎÖG*HB¡O<º2#ñŒAƒ–¡B˜´É$¥›É:FÀÔx¾u?XÜÏÓvN©RS{2ʈãk9rmP¼Qq̳ è¼ÐFׄ^¡Öì fE“F4A…!ì/…¦Lƒ… … $%´¾yã@CI¬ á—3PþBÏNÿ<ý°4Ü ËÃ#ØÍ~âW«rEñw‹eùMMHß²`¬Öó½íf³:‹k˜¯÷}Z!ã¿<¥,\#öµÀ¯aÒNÆIé,Ћ–lŽ#Àæ9ÀÒS·I’½-Ïp Äz¤Š Â* ­íÄ9­< h>׍3ZkËU¹§˜ŒŠ±f­’¤º³Q ÏB?‹#µíÃ¥®@(Gs«†vI¥Mµ‹Á©e~2ú³ÁP4ìÕi‚²Ê^ö@-DþÓàlÜOÍ]n"µã:žpsŽ¢:! Aõ.ç~ÓBûH÷JCÌ]õVƒd «ú´QÙEA–¯¯Œ!.ˆˆëQ±ù œ·Ì!Õâ )ùL„ÅÀlÚè5@B…o´Æ¸XÓ&Û…O«˜”_#‡ƒ„ûÈt!¤ÁÏ›ÎÝŠ?c9 â\>lÓÁVÄÑ™£eØY]:fÝ–—ù+p{™ðè û³”g±OƒÚSù£áÁÊ„ä,ï7š²G ÕÌBk)~ÑiCµ|h#u¤¶îK¨² #²vݯGãeÖ϶ú…¾múÀ¶þÔñ‚Š9'^($¤§ò “š½{éúp÷J›ušS¹áªCÂubÃH9™D™/ZöØÁ‡¦ÝÙŸ·kð*_”.C‹{áXó€‡c¡c€§/šò/&éš÷,àéJþ‰X›fµ“C¨œ®r¬"kL‰Â_q…Z–.ÉL~O µ›zn‚¹À¦Öª7\àHµšÖ %»ÇníV[¥*Õ;ƒ#½¾HK-ÖIÊdÏEÚ#=o÷Óò³´Š: Ç?{¾+9›–‘OEáU·S€˜j"ÄaÜ ŒÛWt› á–c#a»pÔZÞdŽtWê=9éöÊ¢µ~ ë ;Öe‡Œ®:bî3±ýê¢wà¼îpêñ¹¾4 zc¾ðÖÿzdêŒÑÒŝÀ‰s6¤í³ÎÙB¿OZ”+F¤á‡3@Ñëäg©·Ž ˆèª<ù@É{&S„œÕúÀA)‰h:YÀ5^ÂÓŒ°õäU\ ùËÍû#²?Xe¬tu‰^zÒÔãë¼ÛWtEtû …‚g¶Úüâî*moGè¨7%u!]PhÏd™Ý%Îx: VÒ¦ôÊD3ÀŽKÛËãvÆî…N¯ä>Eró–ð`5 Œ%u5XkñÌ*NU%¶áœÊ:Qÿú»“úzyÏ6å-၇¾ ´ ÒÊ]y žO‘w2Äøæ…H’²f±ÎÇ.ª|¥'gîV•Ü .̘¯€šòü¤U~Ù†*¢!?ò wý,}´°ÔÞnïoKq5µb!áÓ3"vAßH¡³¡·G(ÐÎ0Îò¼MG!/ài®@—¬04*`…«é8ªøøló“ˆÊ”èù¤…ßÊoÿé'ËuÌÖ5×È¡§ˆˆfŽë9}hìâ_!!¯  B&Ëö¶‰ÀAÙNVŸ Wh›¸®XÑJì¨ú“¿÷3uj²˜¨ÍÎìë±aúŠÝå¯ð*Ó¨ôJ“yºØ)m°WýOè68†ŸÏ2—‰Ïüꪫٚ¥‹l1 ø ÏÄFjêµvÌbü¦èÝx:X±¢H=MÐß—,ˆÉÇ´(9ú¾^ÅÚ4¿m‡$âX‘å%(AlZo@½¨UOÌÕ”1ø¸jÎÀÃÃ_ µ‘Ü.œº¦Ut: Æï’!=¯uwû#,“pþÇúŒø(é@?³ü¥‘Mo §—s@Œ#)§ŒùkL}NOÆêA›¸~r½¼ÙA—HJ«eˆÖ´*¡ÓpÌŸö.m<-"³ûÈ$¬_6­åf£ïÚâj1y§ÕJ½@dÞÁr&Í\Z%D£Íñ·AZ Û³øüd/ªAi†/Й~  ‡âĮҮÏh§°b—›Û«mJžòG'[ÈYýŒ¦9psl ýÁ ®±f¦x,‰½tN ‚Xª9 ÙÖH.«Lo0×?͹m¡å†Ѽ+›2ƒF ±Ê8 7Hցϓ²Æ–m9…òŸï]Â1äN†VLâCˆU .ÿ‰Ts +ÅÎx(%¦u]6AF Š ØF鈄‘ |¢¶c±soŒ/t[a¾–û:s·`i햍ê›ËchÈ…8ßÀUÜewŒðNOƒõD%q#éû\9¤x¹&UE×G¥ Í—™$ð E6-‡¼!ýpãÔM˜ Âsìe¯ñµK¢Ç¡ùôléœ4Ö£”À Š®Ðc ^¨À}ÙËŸ§›ºê{ÊuÉC ×Sr€¤’fÉ*j!úÓ’Gsùìoîßîn%ò· àc Wp÷$¨˜)û»H ×8ŽÒ€Zj¤3ÀÙºY'Ql¦py{-6íÔCeiØp‘‡XÊîÆUߢ܂ž£Xé¼Y8þ©ëgñß}é.ÎógÒ„ÃØËø¯»™§Xýy M%@NŠ À(~áÐvu7&•,Ù˜ó€uP‡^^®=_E„jt’ 403WebShell
403Webshell
Server IP : 159.198.67.129  /  Your IP : 216.73.216.244
Web Server : LiteSpeed
System : Linux server166.web-hosting.com 4.18.0-513.18.1.lve.el8.x86_64 #1 SMP Thu Feb 22 12:55:50 UTC 2024 x86_64
User : trooaisr ( 4033)
PHP Version : 7.4.33
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /proc/self/root/opt/hc_python/lib/python3.12/site-packages/greenlet/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /proc/self/root/opt/hc_python/lib/python3.12/site-packages/greenlet/TGreenlet.cpp
/* -*- indent-tabs-mode: nil; tab-width: 4; -*- */
/**
 * Implementation of greenlet::Greenlet.
 *
 * Format with:
 *  clang-format -i --style=file src/greenlet/greenlet.c
 *
 *
 * Fix missing braces with:
 *   clang-tidy src/greenlet/greenlet.c -fix -checks="readability-braces-around-statements"
*/
#ifndef TGREENLET_CPP
#define TGREENLET_CPP
#include "greenlet_internal.hpp"
#include "TGreenlet.hpp"


#include "TGreenletGlobals.cpp"
#include "TThreadStateDestroy.cpp"

namespace greenlet {

Greenlet::Greenlet(PyGreenlet* p)
    :  Greenlet(p, StackState())
{
}

Greenlet::Greenlet(PyGreenlet* p, const StackState& initial_stack)
    :  _self(p), stack_state(initial_stack)
{
    assert(p->pimpl == nullptr);
    p->pimpl = this;
}

Greenlet::~Greenlet()
{
    // XXX: Can't do this. tp_clear is a virtual function, and by the
    // time we're here, we've sliced off our child classes.
    //this->tp_clear();
    this->_self->pimpl = nullptr;
}

bool
Greenlet::force_slp_switch_error() const noexcept
{
    return false;
}

void
Greenlet::release_args()
{
    this->switch_args.CLEAR();
}

/**
 * CAUTION: This will allocate memory and may trigger garbage
 * collection and arbitrary Python code.
 */
OwnedObject
Greenlet::throw_GreenletExit_during_dealloc(const ThreadState& UNUSED(current_thread_state))
{
    // If we're killed because we lost all references in the
    // middle of a switch, that's ok. Don't reset the args/kwargs,
    // we still want to pass them to the parent.
    PyErr_SetString(mod_globs->PyExc_GreenletExit,
                    "Killing the greenlet because all references have vanished.");
    // To get here it had to have run before
    return this->g_switch();
}

inline void
Greenlet::slp_restore_state() noexcept
{
#ifdef SLP_BEFORE_RESTORE_STATE
    SLP_BEFORE_RESTORE_STATE();
#endif
    this->stack_state.copy_heap_to_stack(
           this->thread_state()->borrow_current()->stack_state);
}


inline int
Greenlet::slp_save_state(char *const stackref) noexcept
{
    // XXX: This used to happen in the middle, before saving, but
    // after finding the next owner. Does that matter? This is
    // only defined for Sparc/GCC where it flushes register
    // windows to the stack (I think)
#ifdef SLP_BEFORE_SAVE_STATE
    SLP_BEFORE_SAVE_STATE();
#endif
    return this->stack_state.copy_stack_to_heap(stackref,
                                                this->thread_state()->borrow_current()->stack_state);
}

/**
 * CAUTION: This will allocate memory and may trigger garbage
 * collection and arbitrary Python code.
 */
OwnedObject
Greenlet::on_switchstack_or_initialstub_failure(
    Greenlet* target,
    const Greenlet::switchstack_result_t& err,
    const bool target_was_me,
    const bool was_initial_stub)
{
    // If we get here, either g_initialstub()
    // failed, or g_switchstack() failed. Either one of those
    // cases SHOULD leave us in the original greenlet with a valid stack.
    if (!PyErr_Occurred()) {
        PyErr_SetString(
            PyExc_SystemError,
            was_initial_stub
            ? "Failed to switch stacks into a greenlet for the first time."
            : "Failed to switch stacks into a running greenlet.");
    }
    this->release_args();

    if (target && !target_was_me) {
        target->murder_in_place();
    }

    assert(!err.the_new_current_greenlet);
    assert(!err.origin_greenlet);
    return OwnedObject();

}

OwnedGreenlet
Greenlet::g_switchstack_success() noexcept
{
    PyThreadState* tstate = PyThreadState_GET();
    // restore the saved state
    this->python_state >> tstate;
    this->exception_state >> tstate;

    // The thread state hasn't been changed yet.
    ThreadState* thread_state = this->thread_state();
    OwnedGreenlet result(thread_state->get_current());
    thread_state->set_current(this->self());
    //assert(thread_state->borrow_current().borrow() == this->_self);
    return result;
}

Greenlet::switchstack_result_t
Greenlet::g_switchstack(void)
{
    // if any of these assertions fail, it's likely because we
    // switched away and tried to switch back to us. Early stages of
    // switching are not reentrant because we re-use ``this->args()``.
    // Switching away would happen if we trigger a garbage collection
    // (by just using some Python APIs that happen to allocate Python
    // objects) and some garbage had weakref callbacks or __del__ that
    // switches (people don't write code like that by hand, but with
    // gevent it's possible without realizing it)
    assert(this->args() || PyErr_Occurred());
    { /* save state */
        if (this->thread_state()->is_current(this->self())) {
            // Hmm, nothing to do.
            // TODO: Does this bypass trace events that are
            // important?
            return switchstack_result_t(0,
                                        this, this->thread_state()->borrow_current());
        }
        BorrowedGreenlet current = this->thread_state()->borrow_current();
        PyThreadState* tstate = PyThreadState_GET();

        current->python_state << tstate;
        current->exception_state << tstate;
        this->python_state.will_switch_from(tstate);
        switching_thread_state = this;
        current->expose_frames();
    }
    assert(this->args() || PyErr_Occurred());
    // If this is the first switch into a greenlet, this will
    // return twice, once with 1 in the new greenlet, once with 0
    // in the origin.
    int err;
    if (this->force_slp_switch_error()) {
        err = -1;
    }
    else {
        err = slp_switch();
    }

    if (err < 0) { /* error */
        // Tested by
        // test_greenlet.TestBrokenGreenlets.test_failed_to_slp_switch_into_running
        //
        // It's not clear if it's worth trying to clean up and
        // continue here. Failing to switch stacks is a big deal which
        // may not be recoverable (who knows what state the stack is in).
        // Also, we've stolen references in preparation for calling
        // ``g_switchstack_success()`` and we don't have a clean
        // mechanism for backing that all out.
        Py_FatalError("greenlet: Failed low-level slp_switch(). The stack is probably corrupt.");
    }

    // No stack-based variables are valid anymore.

    // But the global is volatile so we can reload it without the
    // compiler caching it from earlier.
    Greenlet* greenlet_that_switched_in = switching_thread_state; // aka this
    switching_thread_state = nullptr;
    // except that no stack variables are valid, we would:
    // assert(this == greenlet_that_switched_in);

    // switchstack success is where we restore the exception state,
    // etc. It returns the origin greenlet because its convenient.

    OwnedGreenlet origin = greenlet_that_switched_in->g_switchstack_success();
    assert(greenlet_that_switched_in->args() || PyErr_Occurred());
    return switchstack_result_t(err, greenlet_that_switched_in, origin);
}


inline void
Greenlet::check_switch_allowed() const
{
    // TODO: Make this take a parameter of the current greenlet,
    // or current main greenlet, to make the check for
    // cross-thread switching cheaper. Surely somewhere up the
    // call stack we've already accessed the thread local variable.

    // We expect to always have a main greenlet now; accessing the thread state
    // created it. However, if we get here and cleanup has already
    // begun because we're a greenlet that was running in a
    // (now dead) thread, these invariants will not hold true. In
    // fact, accessing `this->thread_state` may not even be possible.

    // If the thread this greenlet was running in is dead,
    // we'll still have a reference to a main greenlet, but the
    // thread state pointer we have is bogus.
    // TODO: Give the objects an API to determine if they belong
    // to a dead thread.

    const BorrowedMainGreenlet main_greenlet = this->find_main_greenlet_in_lineage();

    if (!main_greenlet) {
        throw PyErrOccurred(mod_globs->PyExc_GreenletError,
                            "cannot switch to a garbage collected greenlet");
    }

    if (!main_greenlet->thread_state()) {
        throw PyErrOccurred(mod_globs->PyExc_GreenletError,
                            "cannot switch to a different thread (which happens to have exited)");
    }

    // The main greenlet we found was from the .parent lineage.
    // That may or may not have any relationship to the main
    // greenlet of the running thread. We can't actually access
    // our this->thread_state members to try to check that,
    // because it could be in the process of getting destroyed,
    // but setting the main_greenlet->thread_state member to NULL
    // may not be visible yet. So we need to check against the
    // current thread state (once the cheaper checks are out of
    // the way)
    const BorrowedMainGreenlet current_main_greenlet = GET_THREAD_STATE().state().borrow_main_greenlet();
    if (
        // lineage main greenlet is not this thread's greenlet
        current_main_greenlet != main_greenlet
        || (
            // atteched to some thread
            this->main_greenlet()
            // XXX: Same condition as above. Was this supposed to be
            // this->main_greenlet()?
            && current_main_greenlet != main_greenlet)
        // switching into a known dead thread (XXX: which, if we get here,
        // is bad, because we just accessed the thread state, which is
        // gone!)
        || (!current_main_greenlet->thread_state())) {
        // CAUTION: This may trigger memory allocations, gc, and
        // arbitrary Python code.
        throw PyErrOccurred(
            mod_globs->PyExc_GreenletError,
            "Cannot switch to a different thread\n\tCurrent:  %R\n\tExpected: %R",
            current_main_greenlet, main_greenlet);
    }
}

const OwnedObject
Greenlet::context() const
{
    using greenlet::PythonStateContext;
    OwnedObject result;

    if (this->is_currently_running_in_some_thread()) {
        /* Currently running greenlet: context is stored in the thread state,
           not the greenlet object. */
        if (GET_THREAD_STATE().state().is_current(this->self())) {
            result = PythonStateContext::context(PyThreadState_GET());
        }
        else {
            throw ValueError(
                            "cannot get context of a "
                            "greenlet that is running in a different thread");
        }
    }
    else {
        /* Greenlet is not running: just return context. */
        result = this->python_state.context();
    }
    if (!result) {
        result = OwnedObject::None();
    }
    return result;
}


void
Greenlet::context(BorrowedObject given)
{
    using greenlet::PythonStateContext;
    if (!given) {
        throw AttributeError("can't delete context attribute");
    }
    if (given.is_None()) {
        /* "Empty context" is stored as NULL, not None. */
        given = nullptr;
    }

    //checks type, incrs refcnt
    greenlet::refs::OwnedContext context(given);
    PyThreadState* tstate = PyThreadState_GET();

    if (this->is_currently_running_in_some_thread()) {
        if (!GET_THREAD_STATE().state().is_current(this->self())) {
            throw ValueError("cannot set context of a greenlet"
                             " that is running in a different thread");
        }

        /* Currently running greenlet: context is stored in the thread state,
           not the greenlet object. */
        OwnedObject octx = OwnedObject::consuming(PythonStateContext::context(tstate));
        PythonStateContext::context(tstate, context.relinquish_ownership());
    }
    else {
        /* Greenlet is not running: just set context. Note that the
           greenlet may be dead.*/
        this->python_state.context() = context;
    }
}

/**
 * CAUTION: May invoke arbitrary Python code.
 *
 * Figure out what the result of ``greenlet.switch(arg, kwargs)``
 * should be and transfers ownership of it to the left-hand-side.
 *
 * If switch() was just passed an arg tuple, then we'll just return that.
 * If only keyword arguments were passed, then we'll pass the keyword
 * argument dict. Otherwise, we'll create a tuple of (args, kwargs) and
 * return both.
 *
 * CAUTION: This may allocate a new tuple object, which may
 * cause the Python garbage collector to run, which in turn may
 * run arbitrary Python code that switches.
 */
OwnedObject& operator<<=(OwnedObject& lhs, greenlet::SwitchingArgs& rhs) noexcept
{
    // Because this may invoke arbitrary Python code, which could
    // result in switching back to us, we need to get the
    // arguments locally on the stack.
    assert(rhs);
    OwnedObject args = rhs.args();
    OwnedObject kwargs = rhs.kwargs();
    rhs.CLEAR();
    // We shouldn't be called twice for the same switch.
    assert(args || kwargs);
    assert(!rhs);

    if (!kwargs) {
        lhs = args;
    }
    else if (!PyDict_Size(kwargs.borrow())) {
        lhs = args;
    }
    else if (!PySequence_Length(args.borrow())) {
        lhs = kwargs;
    }
    else {
        // PyTuple_Pack allocates memory, may GC, may run arbitrary
        // Python code.
        lhs = OwnedObject::consuming(PyTuple_Pack(2, args.borrow(), kwargs.borrow()));
    }
    return lhs;
}

static OwnedObject
g_handle_exit(const OwnedObject& greenlet_result)
{
    if (!greenlet_result && mod_globs->PyExc_GreenletExit.PyExceptionMatches()) {
        /* catch and ignore GreenletExit */
        PyErrFetchParam val;
        PyErr_Fetch(PyErrFetchParam(), val, PyErrFetchParam());
        if (!val) {
            return OwnedObject::None();
        }
        return OwnedObject(val);
    }

    if (greenlet_result) {
        // package the result into a 1-tuple
        // PyTuple_Pack increments the reference of its arguments,
        // so we always need to decref the greenlet result;
        // the owner will do that.
        return OwnedObject::consuming(PyTuple_Pack(1, greenlet_result.borrow()));
    }

    return OwnedObject();
}



/**
 * May run arbitrary Python code.
 */
OwnedObject
Greenlet::g_switch_finish(const switchstack_result_t& err)
{
    assert(err.the_new_current_greenlet == this);

    ThreadState& state = *this->thread_state();
    // Because calling the trace function could do arbitrary things,
    // including switching away from this greenlet and then maybe
    // switching back, we need to capture the arguments now so that
    // they don't change.
    OwnedObject result;
    if (this->args()) {
        result <<= this->args();
    }
    else {
        assert(PyErr_Occurred());
    }
    assert(!this->args());
    try {
        // Our only caller handles the bad error case
        assert(err.status >= 0);
        assert(state.borrow_current() == this->self());
        if (OwnedObject tracefunc = state.get_tracefunc()) {
            assert(result || PyErr_Occurred());
            g_calltrace(tracefunc,
                        result ? mod_globs->event_switch : mod_globs->event_throw,
                        err.origin_greenlet,
                        this->self());
        }
        // The above could have invoked arbitrary Python code, but
        // it couldn't switch back to this object and *also*
        // throw an exception, so the args won't have changed.

        if (PyErr_Occurred()) {
            // We get here if we fell of the end of the run() function
            // raising an exception. The switch itself was
            // successful, but the function raised.
            // valgrind reports that memory allocated here can still
            // be reached after a test run.
            throw PyErrOccurred::from_current();
        }
        return result;
    }
    catch (const PyErrOccurred&) {
        /* Turn switch errors into switch throws */
        /* Turn trace errors into switch throws */
        this->release_args();
        throw;
    }
}

void
Greenlet::g_calltrace(const OwnedObject& tracefunc,
                      const greenlet::refs::ImmortalEventName& event,
                      const BorrowedGreenlet& origin,
                      const BorrowedGreenlet& target)
{
    PyErrPieces saved_exc;
    try {
        TracingGuard tracing_guard;
        // TODO: We have saved the active exception (if any) that's
        // about to be raised. In the 'throw' case, we could provide
        // the exception to the tracefunction, which seems very helpful.
        tracing_guard.CallTraceFunction(tracefunc, event, origin, target);
    }
    catch (const PyErrOccurred&) {
        // In case of exceptions trace function is removed,
        // and any existing exception is replaced with the tracing
        // exception.
        GET_THREAD_STATE().state().set_tracefunc(Py_None);
        throw;
    }

    saved_exc.PyErrRestore();
    assert(
        (event == mod_globs->event_throw && PyErr_Occurred())
        || (event == mod_globs->event_switch && !PyErr_Occurred())
    );
}

void
Greenlet::murder_in_place()
{
    if (this->active()) {
        assert(!this->is_currently_running_in_some_thread());
        this->deactivate_and_free();
    }
}

inline void
Greenlet::deactivate_and_free()
{
    if (!this->active()) {
        return;
    }
    // Throw away any saved stack.
    this->stack_state = StackState();
    assert(!this->stack_state.active());
    // Throw away any Python references.
    // We're holding a borrowed reference to the last
    // frame we executed. Since we borrowed it, the
    // normal traversal, clear, and dealloc functions
    // ignore it, meaning it leaks. (The thread state
    // object can't find it to clear it when that's
    // deallocated either, because by definition if we
    // got an object on this list, it wasn't
    // running and the thread state doesn't have
    // this frame.)
    // So here, we *do* clear it.
    this->python_state.tp_clear(true);
}

bool
Greenlet::belongs_to_thread(const ThreadState* thread_state) const
{
    if (!this->thread_state() // not running anywhere, or thread
                              // exited
        || !thread_state) { // same, or there is no thread state.
        return false;
    }
    return true;
}


void
Greenlet::deallocing_greenlet_in_thread(const ThreadState* current_thread_state)
{
    /* Cannot raise an exception to kill the greenlet if
       it is not running in the same thread! */
    if (this->belongs_to_thread(current_thread_state)) {
        assert(current_thread_state);
        // To get here it had to have run before
        /* Send the greenlet a GreenletExit exception. */

        // We don't care about the return value, only whether an
        // exception happened.
        this->throw_GreenletExit_during_dealloc(*current_thread_state);
        return;
    }

    // Not the same thread! Temporarily save the greenlet
    // into its thread's deleteme list, *if* it exists.
    // If that thread has already exited, and processed its pending
    // cleanup, we'll never be able to clean everything up: we won't
    // be able to raise an exception.
    // That's mostly OK! Since we can't add it to a list, our refcount
    // won't increase, and we'll go ahead with the DECREFs later.

    ThreadState *const  thread_state = this->thread_state();
    if (thread_state) {
        thread_state->delete_when_thread_running(this->self());
    }
    else {
        // The thread is dead, we can't raise an exception.
        // We need to make it look non-active, though, so that dealloc
        // finishes killing it.
        this->deactivate_and_free();
    }
    return;
}


int
Greenlet::tp_traverse(visitproc visit, void* arg)
{

    int result;
    if ((result = this->exception_state.tp_traverse(visit, arg)) != 0) {
        return result;
    }
    //XXX: This is ugly. But so is handling everything having to do
    //with the top frame.
    bool visit_top_frame = this->was_running_in_dead_thread();
    // When true, the thread is dead. Our implicit weak reference to the
    // frame is now all that's left; we consider ourselves to
    // strongly own it now.
    if ((result = this->python_state.tp_traverse(visit, arg, visit_top_frame)) != 0) {
        return result;
    }
    return 0;
}

int
Greenlet::tp_clear()
{
    bool own_top_frame = this->was_running_in_dead_thread();
    this->exception_state.tp_clear();
    this->python_state.tp_clear(own_top_frame);
    return 0;
}

bool Greenlet::is_currently_running_in_some_thread() const
{
    return this->stack_state.active() && !this->python_state.top_frame();
}

#if GREENLET_PY312
void GREENLET_NOINLINE(Greenlet::expose_frames)()
{
    if (!this->python_state.top_frame()) {
        return;
    }

    _PyInterpreterFrame* last_complete_iframe = nullptr;
    _PyInterpreterFrame* iframe = this->python_state.top_frame()->f_frame;
    while (iframe) {
        // We must make a copy before looking at the iframe contents,
        // since iframe might point to a portion of the greenlet's C stack
        // that was spilled when switching greenlets.
        _PyInterpreterFrame iframe_copy;
        this->stack_state.copy_from_stack(&iframe_copy, iframe, sizeof(*iframe));
        if (!_PyFrame_IsIncomplete(&iframe_copy)) {
            // If the iframe were OWNED_BY_CSTACK then it would always be
            // incomplete. Since it's not incomplete, it's not on the C stack
            // and we can access it through the original `iframe` pointer
            // directly.  This is important since GetFrameObject might
            // lazily _create_ the frame object and we don't want the
            // interpreter to lose track of it.
            assert(iframe_copy.owner != FRAME_OWNED_BY_CSTACK);

            // We really want to just write:
            //     PyFrameObject* frame = _PyFrame_GetFrameObject(iframe);
            // but _PyFrame_GetFrameObject calls _PyFrame_MakeAndSetFrameObject
            // which is not a visible symbol in libpython. The easiest
            // way to get a public function to call it is using
            // PyFrame_GetBack, which is defined as follows:
            //     assert(frame != NULL);
            //     assert(!_PyFrame_IsIncomplete(frame->f_frame));
            //     PyFrameObject *back = frame->f_back;
            //     if (back == NULL) {
            //         _PyInterpreterFrame *prev = frame->f_frame->previous;
            //         prev = _PyFrame_GetFirstComplete(prev);
            //         if (prev) {
            //             back = _PyFrame_GetFrameObject(prev);
            //         }
            //     }
            //     return (PyFrameObject*)Py_XNewRef(back);
            if (!iframe->frame_obj) {
                PyFrameObject dummy_frame;
                _PyInterpreterFrame dummy_iframe;
                dummy_frame.f_back = nullptr;
                dummy_frame.f_frame = &dummy_iframe;
                // force the iframe to be considered complete without
                // needing to check its code object:
                dummy_iframe.owner = FRAME_OWNED_BY_GENERATOR;
                dummy_iframe.previous = iframe;
                assert(!_PyFrame_IsIncomplete(&dummy_iframe));
                // Drop the returned reference immediately; the iframe
                // continues to hold a strong reference
                Py_XDECREF(PyFrame_GetBack(&dummy_frame));
                assert(iframe->frame_obj);
            }

            // This is a complete frame, so make the last one of those we saw
            // point at it, bypassing any incomplete frames (which may have
            // been on the C stack) in between the two. We're overwriting
            // last_complete_iframe->previous and need that to be reversible,
            // so we store the original previous ptr in the frame object
            // (which we must have created on a previous iteration through
            // this loop). The frame object has a bunch of storage that is
            // only used when its iframe is OWNED_BY_FRAME_OBJECT, which only
            // occurs when the frame object outlives the frame's execution,
            // which can't have happened yet because the frame is currently
            // executing as far as the interpreter is concerned. So, we can
            // reuse it for our own purposes.
            assert(iframe->owner == FRAME_OWNED_BY_THREAD
                   || iframe->owner == FRAME_OWNED_BY_GENERATOR);
            if (last_complete_iframe) {
                assert(last_complete_iframe->frame_obj);
                memcpy(&last_complete_iframe->frame_obj->_f_frame_data[0],
                       &last_complete_iframe->previous, sizeof(void *));
                last_complete_iframe->previous = iframe;
            }
            last_complete_iframe = iframe;
        }
        // Frames that are OWNED_BY_FRAME_OBJECT are linked via the
        // frame's f_back while all others are linked via the iframe's
        // previous ptr. Since all the frames we traverse are running
        // as far as the interpreter is concerned, we don't have to
        // worry about the OWNED_BY_FRAME_OBJECT case.
        iframe = iframe_copy.previous;
    }

    // Give the outermost complete iframe a null previous pointer to
    // account for any potential incomplete/C-stack iframes between it
    // and the actual top-of-stack
    if (last_complete_iframe) {
        assert(last_complete_iframe->frame_obj);
        memcpy(&last_complete_iframe->frame_obj->_f_frame_data[0],
               &last_complete_iframe->previous, sizeof(void *));
        last_complete_iframe->previous = nullptr;
    }
}
#else
void Greenlet::expose_frames()
{

}
#endif

}; // namespace greenlet
#endif

Youez - 2016 - github.com/yon3zu
LinuXploit