ó
    X=Œj   ã                   ó$  • S r SSKrSSKrSSKrSSKrSSKr\" \R                  R                  SS5      5      r	\
" \R                  R                  SS5      5      rS r " S S	5      rS
 rS rS r\S:X  a  \" 5         \R$                  " S5        gg)aT  Reproducer for the free-threaded GC crash in issue #515.

https://github.com/python-greenlet/greenlet/issues/515

Before the fix, ``set_initial_state`` copied the parent thread state's
``_PyCStackRef`` list head into each new greenlet. Those nodes sit on the
parent greenlet's C stack, so once the child starts running on its own stack
and overwrites that region their ``next`` pointers dangle. The free-threaded
collector walks ``c_stack_refs`` for every thread, so a GC on any thread ends
up chasing those dangling nodes (inside ``gc_collect_main`` ->
``gc_visit_thread_stacks``) while such a child is active, and segfaults.

The fiddly part is getting a *non-empty* list to inherit at all. The
interpreter only holds a ``_PyCStackRef`` transiently, while it is resolving an
attribute -- ``_Py_LoadAttr_StackRefSteal`` pins ``self`` across ``obj.attr()``
-- so the greenlet has to be primed from inside that window. Priming it from a
property getter does exactly that; it is also the same deep-attribute context
Playwright's sync bridge happens to start its fiber from. A churn thread then
keeps the collector busy while the dispatcher runs on its stale list.

A fixed build prints "ISSUE 515 OK"; a regressed one segfaults in about a
second. With-GIL builds are unaffected -- ordinary refcounting keeps the nodes
alive -- so there it simply prints the OK line.
é    NÚREPRO_SECONDSÚ4ÚREPRO_THREADSÚ6c                  óv   • SR                  5       R                  5       R                  5       R                  5       $ )NÚabc)ÚupperÚlowerÚstripÚtitle© ó    Úo/Users/stevendouglas/BidBrain/.venv/lib/python3.13/site-packages/greenlet/tests/fail_issue_515_freethread_gc.pyÚ_busyr   &   s+   € ð �;‰;‹=×ÑÓ ×&Ñ&Ó(×.Ñ.Ó0Ð0r   c                   ó<   • \ rS rSrS rS r\S 5       rS rS r	Sr
g)	ÚBridgeé,   c                 óŽ   • Xl         [        R                  " 5       U l        [        R                  " U R                  5      U l        g ©N)ÚstopÚgreenletÚ
getcurrentÚmainÚ_loopÚdisp)Úselfr   s     r   Ú__init__ÚBridge.__init__-   s-   € ØŒ	Ü×'Ò'Ó)ˆŒ	Ü×%Ò% d§j¡jÓ1ˆ�	r   c                 óÆ   • U R                   S   (       dM  [        S5       H  n[        5         M     U R                  R	                  5         U R                   S   (       d  ML  g g )Nr   é2   )r   Úranger   r   Úswitch)r   Ú_s     r   r   ÚBridge._loop2   s?   € Ø—)‘)˜A—,Ü˜2–Y�Ü–ñ à�I‰I×ÑÔð —)‘)˜A—,“,r   c                 ó8   • U R                   R                  5         g r   ©r   r"   ©r   s    r   Ú_primeÚBridge._prime8   s   € ð
 	�	‰	×ÑÔØr   c                 ó   • U R                   $ r   )r(   r'   s    r   ÚstartÚBridge.start@   s   € ð
 �{‰{Ðr   c                 ó8   • U R                   R                  5         g r   r&   r'   s    r   ÚresumeÚBridge.resumeG   s   € Ø�	‰	×ÑÕr   )r   r   r   N)Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__r   r   Úpropertyr(   r+   r.   Ú__static_attributes__r   r   r   r   r   ,   s*   † ò2ò
ð ñó ðòõr   r   c                 óˆ   • [        U 5      nUR                  5         U S   (       d  UR                  5         U S   (       d  M  g g )Nr   )r   r+   r.   )r   Úbridges     r   Úworkerr8   K   s1   € Ü�D‹\€FØ
‡L�L„Nð �1�gØ�‰Œð �1�g‹gr   c                 óî   • U S   (       df  [        S5       Vs/ s H  oS S.PM	     nn[        X"SS  5       H	  u  p4XCS'   M     US   US   S'   A[        R                  " 5         U S   (       d  Me  g g s  snf )Nr   iô  )ÚiÚnexté   r;   éÿÿÿÿ)r!   ÚzipÚgcÚcollect)r   r:   ÚnodesÚaÚbs        r   ÚchurnrD   T   sr   € Ø�1�gô 27°s´Ó<²¨A $Ô'±ˆÐ<Ü˜ Q R˜yÖ)‰DˆAØˆf‹Iñ *à! !™Hˆˆb‰	�&ÑØÜ
�
Š
Œð �1�g‹gùò =s   ˜A2c            
      ó–  • S/n [         R                  " [        U 4SS9/nU[        [        5       Vs/ s H  n[         R                  " [
        U 4SS9PM      sn-  nU H  nUR                  5         M     [         R                  " 5       R                  [        5        SU S'   U H  nUR                  SS9  M     [        S5        g s  snf )NFT)ÚtargetÚargsÚdaemonr   é   )ÚtimeoutzISSUE 515 OK)Ú	threadingÚThreadrD   r!   ÚNWORKERSr8   r+   ÚEventÚwaitÚDURATIONÚjoinÚprint)r   Úthreadsr#   Úts       r   r   r   `   s²   € Øˆ7€DÜ×Ò¤u°D°7À4ÑHÐI€GØÜœxœó*Ú(�Aô × Ò ¬°d°WÀTÔJÙ(ñ*ñ *€GãˆØ	�‰Ž	ñ ä‡O‚OÓ×Ñœ8Ô$Ø€Dˆ�GÛˆØ	�‰�qˆÓñ ä	ˆ.Õùò*s   ²%CÚ__main__)Ú__doc__r?   ÚosÚsysrK   r   ÚfloatÚenvironÚgetrP   ÚintrM   r   r   r8   rD   r   r0   Úexitr   r   r   Ú<module>r^      sŒ   ðñó0 
Û 	Û 
Û ã ñ �—‘—‘ °Ó5Ó6€Ùˆr�z‰z�~‰~˜o¨sÓ3Ó4€ò1÷ñ ò>ò	òð ˆzÓÙ„FØ‡H‚HˆQ…Kð r   