
    6\h                        d Z ddlZddlmZmZ ddlmZmZmZ ddlm	Z	 ddl
mZmZ ddlZddlZddlZddlZddlZddlZddlZddlZddlZddlZddlZddlZddlmZ ddlmZ dd	lmZ  ej        d
           dZ eed          Zd Z d Z! G d de"          Z# G d dej$                  Z% G d dej&                  Z' G d de'          Z( G d de'          Z) G d de'          Z* G d de'          Z+ G d dej$                  Z, G d  d!e'          Z- G d" d#e'          Z. G d$ d%ej/                  Z/ G d& d'ej0                  Z1 ej2        ej3        du d(           G d) d*ej0                              Z4 G d+ d,ej5                  Z5 G d- d.ej0                  Z6 G d/ d0ej7                  Z7 G d1 d2ej8                  Z8 G d3 d4ej9                  Z9 G d5 d6ej:                  Z: G d7 d8ej&                  Z; G d9 d:ej&                  Z< G d; d<ej&                  Z=e>d=k    r ej?                     dS dS )>z!
Tests for the threading module.
    N)threading_helperrequires_subprocess)verbosecpython_only	os_helper)import_module)assert_python_okassert_python_failure)mock)
lock_tests)supportT)module)netbsd5zhp-ux11gettotalrefcountc                 
   t           j        s t          j        d          |           S t          j        t          v r t          j        d          |           S t           j        r t          j        d          |           S | S )Nzrequires working os.fork()z*due to known OS bug related to thread+forkz?libasan has a pthread_create() dead lock related to thread+fork)r   has_fork_supportunittestskipsysplatformplatforms_to_skipHAVE_ASAN_FORK_BUG)tests    =/opt/python-3.11.14/usr/lib/python3.11/test/test_threading.pyskip_unless_reliable_forkr   (   s    # A:x}9::4@@@
|(((Jx}IJJ4PPP! f_x}^__`deeeK    c                     |                      t          t          dt          j                   t          j        t          _        d S )N
excepthook)
addCleanupsetattr	threadingr   __excepthook__)testcases    r   restore_default_excepthookr$   2   s0    L):NOOO$3Ir   c                   &    e Zd Zd Zd Zd Zd ZdS )Counterc                     d| _         d S )Nr   valueselfs    r   __init__zCounter.__init__9   s    


r   c                 &    | xj         dz  c_         d S N   r(   r*   s    r   inczCounter.inc;       

a



r   c                 &    | xj         dz  c_         d S r.   r(   r*   s    r   deczCounter.dec=   r1   r   c                     | j         S Nr(   r*   s    r   getzCounter.get?   s
    zr   N)__name__
__module____qualname__r,   r0   r3   r6    r   r   r&   r&   8   sP                  r   r&   c                       e Zd Zd Zd ZdS )
TestThreadc                     t           j                            | |           || _        || _        || _        || _        d S )Nname)r!   Threadr,   r#   semamutexnrunning)r+   r?   r#   rA   rB   rC   s         r   r,   zTestThread.__init__C   s>    !!$T!222 	
 r   c                    t          j                     dz  }t          rt          d| j        |dz  fz             | j        5  | j        5  | j                                         t          r't          | j                                        d           | j	        
                    | j                                        d           d d d            n# 1 swxY w Y   t          j        |           t          rt          d| j        d           | j        5  | j                                         | j	                            | j                                        d           t          r0t          d	| j        | j                                        fz             d d d            n# 1 swxY w Y   d d d            d S # 1 swxY w Y   d S )
Ng     @ztask %s will run for %.1f usecg    .Aztasks are running   taskdoner   z$%s is finished. %d tasks are running)randomr   printr?   rA   rB   rC   r0   r6   r#   assertLessEqualtimesleepr3   assertGreaterEqual)r+   delays     r   runzTestThread.runJ   s   ') 	,29eck*+ , , , Y 	< 	< F F!!### D$-++--/BCCC--dm.?.?.A.A1EEE	F F F F F F F F F F F F F F F Ju 1fdi000 < <!!###001B1B1D1DaHHH <@9dm&7&7&9&9:; < < <	< < < < < < < < < < < < < < <	< 	< 	< 	< 	< 	< 	< 	< 	< 	< 	< 	< 	< 	< 	< 	< 	< 	<s\   F9	A:CF9C	F9C	;F9BF!F9!F%	%F9(F%	)F99F= F=N)r7   r8   r9   r,   rO   r:   r   r   r<   r<   B   s2        ! ! !< < < < <r   r<   c                       e Zd Zd Zd ZdS )BaseTestCasec                 6    t          j                    | _        d S r5   )r   threading_setup_threadsr*   s    r   setUpzBaseTestCase.setUpd   s    (8::r   c                 h    t          j        | j          t          j                                         d S r5   )r   threading_cleanuprT   r   r   reap_childrenr*   s    r   tearDownzBaseTestCase.tearDowng   s,    *DM::""$$$$$r   N)r7   r8   r9   rU   rY   r:   r   r   rQ   rQ   c   s2        ; ; ;% % % % %r   rQ   c                      e Zd ZdZed             Zd Zed             Zd Zd Z	d Z
d Zd	 Zd
 Zd Zd Zd Zd Zd Zd Zd Zd Zd Zed             Zed             Zed             Zd Ze ej         eed          d          d                         Z e ej         eed          d          d                         Z! ej"        e#j$        e%v d           e&j'                     ej         eed          d          d0d                                    Z(d0dZ)d  Z*d! Z+d" Z,d# Z-d$ Z.ed%             Z/d& Z0d' Z1ed(             Z2d) Z3d* Z4d+ Z5 ej        e6d,          d-             Z7d. Z8d/S )1ThreadTestsi'  c                    d }t          j        d          }|                     |j        d           t          j        d          }|                     |j        d           t          j        |d          }|                     |j        d           t          j                            t           dd	
          5  t          j        d          }|                     |j        d           d d d            n# 1 swxY w Y   t          j                            t           dd
          5  t          j                    }|                     |j        d           d d d            n# 1 swxY w Y   t          j                            t           dd
          5  t          j        |          }|                     |j        d           d d d            d S # 1 swxY w Y   d S )Nc                      d S r5   r:   r:   r   r   funcz#ThreadTests.test_name.<locals>.funcq         r   myname1r>   {   123myname2)targetr?   _counter   )return_value zThread-2rE   zThread-3   rd   zThread-5 (func))r!   r@   assertEqualr?   r   patchobject)r+   r^   threads      r   	test_namezThreadTests.test_nameo   sx   !y111i000 !s+++e,,, !I>>>i000Zy*1EE 	6 	6%2...FV[*555	6 	6 	6 	6 	6 	6 	6 	6 	6 	6 	6 	6 	6 	6 	6 Zy*1EE 	6 	6%''FV[*555	6 	6 	6 	6 	6 	6 	6 	6 	6 	6 	6 	6 	6 	6 	6 Zy*1EE 	= 	=%T222FV[*;<<<	= 	= 	= 	= 	= 	= 	= 	= 	= 	= 	= 	= 	= 	= 	= 	= 	= 	=s6   <1C99C= C=+/E&&E*-E*1GGGc                 `    dg}d}dg}d}dgf}dg}| fdf| fdf| fdf| fdf| fd	f| fd
ff}|D ]r\  }}	                      |	|          5  t          j        |	|          }
|
                                 |
                                 d d d            n# 1 swxY w Y   sd S )Nr/   r/   strrr   c                 0                         | d          S r.   rk   argr+   s    r   <lambda>z0ThreadTests.test_args_argument.<locals>.<lambda>   s    4#3#3C#;#; r   c                 0                         | d          S r.   ru   rv   s    r   rx   z0ThreadTests.test_args_argument.<locals>.<lambda>   s    D$4$4S!$<$< r   c                 0                         | d          S Nrr   ru   rv   s    r   rx   z0ThreadTests.test_args_argument.<locals>.<lambda>   s    4#3#3C#?#? r   c                 0                         | d          S r{   ru   rv   s    r   rx   z0ThreadTests.test_args_argument.<locals>.<lambda>   s    D$4$4S%$@$@ r   c                 2                         | dg          S r.   ru   rv   s    r   rx   z0ThreadTests.test_args_argument.<locals>.<lambda>   s    (8(8qc(B(B r   c                 0                         | d          S )Nrq   ru   rv   s    r   rx   z0ThreadTests.test_args_argument.<locals>.<lambda>   s    (8(8d(C(C r   rd   args)subTestr!   r@   startjoin)r+   num_list	num_tuplestr_list	str_tuplelist_in_tupletuple_in_list
test_casesr   rd   ts   `          r   test_args_argumentzThreadTests.test_args_argument   s\    3	7	 ;;;;<<<<<=????@@@@@ABBBBCCCCCD

 ' 	 	LD&V$77  $F>>>			              	 	s   ?B""B&	)B&	c                     t          j                    }t          j                            | t          |                     d S r5   )r!   Lockr   r   check_disallow_instantiationtyper+   locks     r   test_disallow_instantiationz'ThreadTests.test_disallow_instantiation   s5     ~11$T

CCCCCr   c                 l   d}t          j        d          }t          j                    }t                      }g }t	          |          D ]~}t          d|z  | |||          }|                    |           |                     |j                   | 	                    t          |          d           |                                 t          t           d          rjt          d |D                       t          j                    hz  }|                     d |           |                     t#          |          |dz              t$          rt'          d	           |D ]}|                                 |                     |                                           |                     |j        d
           |                     |j                   | 	                    t          |          d           t$          rt'          d           |                     |                                d
           d S )N
   rE   r(   z<thread %d>z^<TestThread\(.*, initial\)>$get_native_idc              3   $   K   | ]}|j         V  d S r5   )	native_id).0r   s     r   	<genexpr>z/ThreadTests.test_various_ops.<locals>.<genexpr>   s$      ::QQ[::::::r   r/   z!waiting for all tasks to completer   z#^<TestThread\(.*, stopped -?\d+\)>$zall tasks done)r!   BoundedSemaphoreRLockr&   ranger<   appendassertIsNoneidentassertRegexreprr   hasattrsetr   assertNotInrk   lenr   rI   r   assertFalseis_aliveassertNotEqualassertIsNotNoner6   )	r+   NUMTASKSrA   rB   
numrunningthreadsir   
native_idss	            r   test_various_opszThreadTests.test_various_ops   s     )222!!YY
x 	 	A=?D$zJJANN1ag&&&T!WW&FGGGGGIIII9o.. 	<::':::::i>U>W>W=XXJT:...S__hl;;; 	75666 	N 	NAFFHHHQZZ\\***+++  )))T!WW&LMMMM 	$"###))1-----r   c                    |                      t          j                    j                   fd}t          j                    g t          j                    5  t          j        |d          }	                                 | 
                    d         |           d d d            n# 1 swxY w Y   t          j        d         = d S )Nc                                           t          j                    j                                                     d S r5   )r   r!   current_threadr   r   )rG   r   s   r   fz9ThreadTests.test_ident_of_no_threading_threads.<locals>.f   s2    LL1339:::HHJJJJJr   r:   r   )r   r!   r   r   Eventr   wait_threads_exit_threadstart_new_threadwaitrk   _active)r+   r   tidrG   r   s      @@r   "test_ident_of_no_threading_threadsz.ThreadTests.test_ident_of_no_threading_threads   s
   Y577=>>>	 	 	 	 	 	   /11 	, 	,*1b11CIIKKKU1Xs+++	, 	, 	, 	, 	, 	, 	, 	, 	, 	, 	, 	, 	, 	, 	,
 eAh'''s   AB..B25B2c                     t           rt          d           	 t          j        d           n'# t          j        $ r t          j        d          w xY w|                                  t          j        d           d S )Nz!with 256 KiB thread stack size...i   4platform does not support changing thread stack sizer   	r   rI   r!   
stack_sizer   errorr   SkipTestr   r*   s    r   test_various_ops_small_stackz(ThreadTests.test_various_ops_small_stack   s     	75666	H ((((} 	H 	H 	H#FH H H	H 	Q	   - $Ac                     t           rt          d           	 t          j        d           n'# t          j        $ r t          j        d          w xY w|                                  t          j        d           d S )Nzwith 1 MiB thread stack size...i   r   r   r   r*   s    r   test_various_ops_large_stackz(ThreadTests.test_various_ops_large_stack   s     	53444	H ****} 	H 	H 	H#FH H H	H 	Qr   c                    d }t          j                    }|                                 t          j                    5  t          j        ||f          }|                                 d d d            n# 1 swxY w Y   |                     |t           j                   | 	                    t           j        |         t           j
                   |                     t           j        |                                                    |                     t          t           j        |                   d           t           j        |= d S )Nc                 T    t          j                     |                                  d S r5   )r!   r   release)rB   s    r   r   z*ThreadTests.test_foreign_thread.<locals>.f   s$     $&&&MMOOOOOr   _DummyThread)r!   r   acquirer   r   r   r   assertInr   assertIsInstancer   
assertTruer   r   r   )r+   r   rB   r   s       r   test_foreign_threadzThreadTests.test_foreign_thread   sI   	 	 	   /11 	 	*1uh77CMMOOO	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	c9,---i/4i6LMMM	)#.7799:::i/455~FFFc"""s   +A55A9<A9c                   	
 t          d          }|j        j        }|j        |j        f|_         G d dt                    	|                    	          }t          j                    }| 	                    |t                     |                     |d           	  |||          }	 	 # 	$ r Y nw xY w	 |                     |d           n# t          $ r Y nw xY wt          j                    t          j                    
 G 	
fdd	t          j                  } |            }d|_        |                                 t&          rt)          d
           t&          rt)          d            |d|          }|                     |d           t&          rt)          d                                           }|                     |           t&          rt)          d           |                     |j                   t&          rt)          d            ||j        |          }|                     |d           t&          rt)          d           
                    t4          j                   |                     |j                   t&          rt)          d           |j        r|                                 d S d S )Nctypesc                       e Zd ZdS )<ThreadTests.test_PyThreadState_SetAsyncExc.<locals>.AsyncExcN)r7   r8   r9   r:   r   r   AsyncExcr     s        Dr   r   r   TzAsyncExc not raisedr/   c                       e Zd Z fdZdS ):ThreadTests.test_PyThreadState_SetAsyncExc.<locals>.Workerc                     t          j                    | _        d| _        	 	                                  t          j        d           )# $ r d| _                                         Y d S w xY w)NFTg?)r!   	get_identidfinishedr   rK   rL   )r+   r   worker_saw_exceptionworker_starteds    r   rO   z>ThreadTests.test_PyThreadState_SetAsyncExc.<locals>.Worker.run9  s    #-// %/(&**,,,
3(   / / /$(DM(,,....../s   *A  A0/A0Nr7   r8   r9   rO   )r   r   r   s   r   Workerr   8  s8        
/ 
/ 
/ 
/ 
/ 
/ 
/ 
/ 
/r   r   z    started worker threadz     trying nonsensical thread idz,    waiting for worker thread to get startedz"    verifying worker hasn't exitedz2    attempting to raise asynch exception in workerz5    waiting for worker to say it caught the exceptiontimeoutz    all OK -- joining worker)r   	pythonapiPyThreadState_SetAsyncExcc_ulong	py_objectargtypes	Exceptionr!   r   r   intassertGreaterfailrk   UnboundLocalErrorr   r@   daemonr   r   rI   r   r   r   r   r   r   SHORT_TIMEOUTr   )r+   r   set_async_exc	exceptionr   resultr   r   retr   r   r   s            @@@r   test_PyThreadState_SetAsyncExcz*ThreadTests.test_PyThreadState_SetAsyncExc  s.   x(((B"(.&2B!C	 	 	 	 	y 	 	 	 $$X..	 !##c3'''3"""	-"]3	22F 	 	 	D		VQ''''  	 	 	D	 #**(00	/ 	/ 	/ 	/ 	/ 	/ 	/ 	/ 	/Y% 	/ 	/ 	/ FHH				 	/-...  	64555r9--###  	B@AAA!!## 	86777$$$ 	HFGGGqtY//### 	KIJJJ!!'*?!@@@
### 	20111: 	FFHHHHH	 	s$   B. .B65B6:C 
CCc                 2   d }t           j        }|t           _        	 t          j        d           }|                     t           j        |j                   |                     |t           j        v d           |t           _        d S # |t           _        w xY w)Nc                  (    t          j                    r5   )r!   ThreadErrorr   s    r   fail_new_threadz7ThreadTests.test_limbo_cleanup.<locals>.fail_new_threadi  s    ')))r   c                      d S r5   r:   r:   r   r   rx   z0ThreadTests.test_limbo_cleanup.<locals>.<lambda>n       r   rj   z:Failed to cleanup _limbo map on failure of Thread.start().)r!   _start_new_threadr@   assertRaisesr   r   r   _limbo)r+   r   r   r   s       r   test_limbo_cleanupzThreadTests.test_limbo_cleanupg  s    	* 	* 	*%7&5	#	< 555Ai3QW===Y%%LN N N +<I'''*;I';;;;s   AB Bc                 x    t          d           t          dd          \  }}}|                     |d           d S )Nr   -caN  if 1:
            import ctypes, sys, time, _thread

            # This lock is used as a simple event variable.
            ready = _thread.allocate_lock()
            ready.acquire()

            # Module globals are cleared before __del__ is run
            # So we save the functions in class dict
            class C:
                ensure = ctypes.pythonapi.PyGILState_Ensure
                release = ctypes.pythonapi.PyGILState_Release
                def __del__(self):
                    state = self.ensure()
                    self.release(state)

            def waitingThread():
                x = C()
                ready.release()
                time.sleep(100)

            _thread.start_new_thread(waitingThread, ())
            ready.acquire()  # Be sure the other thread is waiting.
            sys.exit(42)
            *   )r   r
   rk   r+   rcouterrs       r   test_finalize_running_threadz(ThreadTests.test_finalize_running_threadv  sL     	h,T 4  C2 	R     r   c                 &    t          dd           d S )Nr   aP  if 1:
            import sys, threading

            # A deadlock-killer, to prevent the
            # testsuite to hang forever
            def killer():
                import os, time
                time.sleep(2)
                print('program blocked; aborting')
                os._exit(2)
            t = threading.Thread(target=killer)
            t.daemon = True
            t.start()

            # This is the trace function
            def func(frame, event, arg):
                threading.current_thread()
                return func

            sys.settrace(func)
            )r	   r*   s    r   test_finalize_with_tracez$ThreadTests.test_finalize_with_trace  s'     	   	 	 	 	 	r   c                     t          dd          \  }}}|                     |                                d           |                     |d           d S )Nr   a  if 1:
                import threading
                from time import sleep

                def child():
                    sleep(1)
                    # As a non-daemon thread we SHOULD wake up and nothing
                    # should be torn down yet
                    print("Woke up, sleep function is:", sleep)

                threading.Thread(target=child).start()
                raise SystemExit
            s5   Woke up, sleep function is: <built-in function sleep>r   )r	   rk   stripr  s       r   test_join_nondaemon_on_shutdownz+ThreadTests.test_join_nondaemon_on_shutdown  sf     ( /  C 	D	F 	F 	Fc"""""r   c                    t           j        }t          j                    }	 t	          dd          D ]}}t          j        |dz             t          j        d           }|                                 |                                  |            }| 	                    ||d||fz             ~	 t          j        |           d S # t          j        |           w xY w)Nr/   d   g-C6*?c                      d S r5   r:   r:   r   r   rx   z7ThreadTests.test_enumerate_after_join.<locals>.<lambda>  s    D r   rj   z&#1703448 triggered after %d trials: %s)
r!   	enumerater   getswitchintervalr   setswitchintervalr@   r   r   r   )r+   enumold_intervalr   r   ls         r   test_enumerate_after_joinz%ThreadTests.test_enumerate_after_join  s     ",..
	01c]] G G%a&j111$LL999			DFF  A<1vEG G G GG !,/////C!,////s   BC Cc                 "    G d dt                     }t          |             |d          }t          j        |          }|j                                         ~|                      |            dt          j         |                      z              |d          }t          j        |          }|j                                         ~|                      |            dt          j         |                      z             d S )Nc                       e Zd Zd Zd ZdS )DThreadTests.test_no_refcycle_through_target.<locals>.RunSelfFunctionc                     || _         t          j        | j        | fd| i          | _        | j                                         d S )Nyet_another)rd   r   kwargs)should_raiser!   r@   _runrn   r   )r+   r  s     r   r,   zMThreadTests.test_no_refcycle_through_target.<locals>.RunSelfFunction.__init__  sU     %1!'.di59G7DT6JL L L !!#####r   c                 "    | j         rt          d S r5   )r  
SystemExit)r+   	other_refr  s      r   r  zIThreadTests.test_no_refcycle_through_target.<locals>.RunSelfFunction._run  s    $ %$$% %r   N)r7   r8   r9   r,   r  r:   r   r   RunSelfFunctionr    s2        $ $ $% % % % %r   r   F)r  z%d references still around)msgT)	rm   r$   weakrefrefrn   r   r   r   getrefcount)r+   r   cyclic_objectweak_cyclic_objectraising_cyclic_objectweak_raising_cyclic_objects         r   test_no_refcycle_through_targetz+ThreadTests.test_no_refcycle_through_target  sX   	% 	% 	% 	% 	%f 	% 	% 	% 	#4((('U;;;$[77!!###,,..:!o.@.@.B.BCCD 	 	F 	F 	F !0T B B B%,[1F%G%G"$))+++!4466:!o.H.H.J.JKKL 	 	N 	N 	N 	N 	Nr   c                    t          j                    }|                     t          d          5  |                                 d d d            n# 1 swxY w Y   |                     t          d          5  |                    d           d d d            n# 1 swxY w Y   |                     t          d          5  |                                 d d d            n# 1 swxY w Y   |                     t          d          5  |                    d           d d d            n# 1 swxY w Y   t          j                    }|                     t          d          5  |	                                 d d d            n# 1 swxY w Y   t          j
                    }|                                 |                     t          d          5  |                                 d d d            n# 1 swxY w Y   |                     t          d	          5  t          j                     d d d            n# 1 swxY w Y   |                     t          d
          5  t          j                     d d d            d S # 1 swxY w Y   d S )Nzget the daemon attributezset the daemon attributeTzget the name attributezset the name attributer?   zuse is_set()zuse notify_all()zuse active_count()zuse current_thread())r!   r@   assertWarnsRegexDeprecationWarningisDaemon	setDaemongetNamesetNamer   isSet	Conditionr   	notifyAllactiveCountcurrentThread)r+   r   econds       r   test_old_threading_apiz"ThreadTests.test_old_threading_api  sI    ""#5#>@ @ 	 	JJLLL	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 ""#5#>@ @ 	 	KK	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 ""#5#<> > 	 	IIKKK	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 ""#5#<> > 	 	IIf	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 O""#5~FF 	 	GGIII	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 "$$""#57IJJ 	 	NN	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 ""#57KLL 	$ 	$!###	$ 	$ 	$ 	$ 	$ 	$ 	$ 	$ 	$ 	$ 	$ 	$ 	$ 	$ 	$""#57MNN 	& 	&#%%%	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	&s   AAA6BBB>CC#&C#D''D+.D+ FFFG//G36G3H55H9<H9I<<J J c                     t          j                    }|                     dt          |                     d|_        |                     dt          |                     d S Nr   T)r!   r@   r   r   r   r   r+   r   s     r   test_repr_daemonzThreadTests.test_repr_daemon  sS    477+++hQ(((((r   c                    t          j                    }|                     |j                   t          j        d          }|                     |j                   t          j        d          }|                     |j                   d S )NFr   T)r!   r@   r   r   r   r;  s     r   test_daemon_paramzThreadTests.test_daemon_param  s|    """E***"""D)))!!!!!r   c                     t          j        d          }t          d|          \  }}}|                     |d           |                     |                                d           d S )Nat  
            import atexit
            import os
            import sys
            from test.support import wait_process

            # Import the threading module to register its "at fork" callback
            import threading

            def exit_handler():
                pid = os.fork()
                if not pid:
                    print("child process ok", file=sys.stderr, flush=True)
                    # child process
                else:
                    wait_process(pid, exitcode=0)

            # exit_handler() will be called after threading._shutdown()
            atexit.register(exit_handler)
        r   r   s   child process ok)textwrapdedentr	   rk   rstripr+   code_r  r  s        r   test_fork_at_exitzThreadTests.test_fork_at_exit#  sl         ( 'tT223c"""':;;;;;r   c                     d}t          d|          \  }}}|                     |d           |                     |d           d S )Na  if 1:
            import _thread, threading, os, time

            def background_thread(evt):
                # Creates and registers the _DummyThread instance
                threading.current_thread()
                evt.set()
                time.sleep(10)

            evt = threading.Event()
            _thread.start_new_thread(background_thread, (evt,))
            evt.wait()
            assert threading.active_count() == 2, threading.active_count()
            if os.fork() == 0:
                assert threading.active_count() == 1, threading.active_count()
                os._exit(0)
            else:
                os.wait()
        r   r   r	   rk   rD  s        r   test_dummy_thread_after_forkz(ThreadTests.test_dummy_thread_after_fork?  sR    & 'tT223c"""c"""""r   c                    t          j                    }|                     t           j        |           t          j                            d           t          d          D ]}t          j        d           }|	                                 t          j                    }|dk    r+t          j        |                                rdnd           p|                                 t          j        |d           d S )	Ngư>   c                      d S r5   r:   r:   r   r   rx   z6ThreadTests.test_is_alive_after_fork.<locals>.<lambda>e  r   r   rj   r      r   exitcode)r   r  r   r  r   r   r   r!   r@   r   osfork_exitr   r   wait_process)r+   r  r   r   pids        r   test_is_alive_after_forkz$ThreadTests.test_is_alive_after_forkZ  s     ,..-|<<< 	&&t,,,r 		7 		7A 555AGGIII'))Caxxqzz||34444$S266666		7 		7r   c                     t          j                    }                     |j        d                                |j        t          j                    j                                        |j        t          j                                fd}t          j        |          }|                                 |	                                 d S )N
MainThreadc                                            t          j                    j        t          j                    j                   d S r5   )r   r!   main_threadr   r   r*   s   r   r   z'ThreadTests.test_main_thread.<locals>.fu  sG    	 5 7 7 = ) 8 : : @B B B B Br   rj   )
r!   rZ  rk   r?   r   r   r   r@   r   r   )r+   mainr   ths   `   r   test_main_threadzThreadTests.test_main_threado  s    $&&L111Y%=%?%?%EFFFY%8%:%:;;;	B 	B 	B 	B 	B Q'''




					r   waitpidztest needs os.waitpid()c                     d}t          d|          \  }}}|                                                    dd          }|                     |d           |                     |d           d S )Na!  if 1:
            import os, threading
            from test import support

            ident = threading.get_ident()
            pid = os.fork()
            if pid == 0:
                print("current ident", threading.get_ident() == ident)
                main = threading.main_thread()
                print("main", main.name)
                print("main ident", main.ident == ident)
                print("current is main", threading.current_thread() is main)
            else:
                support.wait_process(pid, exitcode=0)
        r   rh   r   zHcurrent ident True
main MainThread
main ident True
current is main True
r	   decodereplacerk   r+   rE  rF  r  r  datas         r   test_main_thread_after_forkz'ThreadTests.test_main_thread_after_fork|  s|     'tT223zz||##D"--c"""2	3 	3 	3 	3 	3r   c                     d}t          d|          \  }}}|                                                    dd          }|                     |                    d          d           |                     |d           d S )Na%  if 1:
            import os, threading, sys
            from test import support

            def func():
                ident = threading.get_ident()
                pid = os.fork()
                if pid == 0:
                    print("current ident", threading.get_ident() == ident)
                    main = threading.main_thread()
                    print("main", main.name, type(main).__name__)
                    print("main ident", main.ident == ident)
                    print("current is main", threading.current_thread() is main)
                    # stdout is fully buffered because not a tty,
                    # we have to flush before exit.
                    sys.stdout.flush()

            th = threading.Thread(target=func)
            th.start()
            th.join()
        r   r`  rh   utf-8zTcurrent ident True
main Thread-1 (func) Thread
main ident True
current is main True
ra  rd  s         r   /test_main_thread_after_fork_from_nonmain_threadz;ThreadTests.test_main_thread_after_fork_from_nonmain_thread  s    * 'tT223zz||##D"--G,,b1112	 	 	 	 	r   due to known OS bugFc                 $   d|z  }t          ddd|          \  }}}|                                                    dd          }|                     |                                d           |                     ||rdndd|d	z   d
z              d S )NaC  if 1:
            import os, threading, sys, traceback, _thread
            from test import support

            def func(lock):
                ident = threading.get_ident()
                if %s:
                    # call current_thread() before fork to allocate DummyThread
                    current = threading.current_thread()
                    print("current", current.name, type(current).__name__)
                print("ident in _active", ident in threading._active)
                # flush before fork, so child won't flush it again
                sys.stdout.flush()
                pid = os.fork()
                if pid == 0:
                    print("current ident", threading.get_ident() == ident)
                    main = threading.main_thread()
                    print("main", main.name, type(main).__name__)
                    print("main ident", main.ident == ident)
                    print("current is main", threading.current_thread() is main)
                    print("_dangling", [t.name for t in list(threading._dangling)])
                    # stdout is fully buffered because not a tty,
                    # we have to flush before exit.
                    sys.stdout.flush()
                    try:
                        threading._shutdown()
                        os._exit(0)
                    except:
                        traceback.print_exc()
                        sys.stderr.flush()
                        os._exit(1)
                else:
                    try:
                        support.wait_process(pid, exitcode=0)
                    except Exception:
                        # avoid 'could not acquire lock for
                        # <_io.BufferedWriter name='<stderr>'> at interpreter shutdown,'
                        traceback.print_exc()
                        sys.stderr.flush()
                    finally:
                        lock.release()

            join_lock = _thread.allocate_lock()
            join_lock.acquire()
            th = _thread.start_new_thread(func, (join_lock,))
            join_lock.acquire()
        z-Wzignore::DeprecationWarningr   r`  rh   zcurrent Dummy-1 _DummyThread
zident in _active 
zmcurrent ident True
main MainThread _MainThread
main ident True
current is main True
_dangling ['MainThread']
ra  )r+   create_dummyrE  rF  r  r  re  s          r   /test_main_thread_after_fork_from_foreign_threadz;ThreadTests.test_main_thread_after_fork_from_foreign_thread  s    .\ ].b 't-I4QUVV3zz||##D"--r***>JR::PR?\???@66	7 	7 	7 	7 	7r   c                 2    |                      d           d S )NT)rm  )rn  )r+   rm  s     r   -test_main_thread_after_fork_from_dummy_threadz9ThreadTests.test_main_thread_after_fork_from_dummy_thread  s    <<$<OOOOOr   c                     d}t          d|          \  }}}|                                }|                     |d           |                     |                                dgdz             d S )Na  if 1:
            import gc, threading

            main_thread = threading.current_thread()
            assert main_thread is threading.main_thread()  # sanity check

            class RefCycle:
                def __init__(self):
                    self.cycle = self

                def __del__(self):
                    print("GC:",
                          threading.current_thread() is main_thread,
                          threading.main_thread() is main_thread,
                          threading.enumerate() == [main_thread])

            RefCycle()
            gc.collect()  # sanity check
            x = RefCycle()
        r   r   zGC: True True Truerf   )r	   rb  rk   
splitlinesrd  s         r    test_main_thread_during_shutdownz,ThreadTests.test_main_thread_during_shutdown  s|    ( 'tT223zz||c"""**./!3	5 	5 	5 	5 	5r   c                 ^    d}t          d|          \  }}}|                     |d           d S )Na  if 1:
            import os
            import threading
            import time
            import random

            def random_sleep():
                seconds = random.random() * 0.010
                time.sleep(seconds)

            class Sleeper:
                def __del__(self):
                    random_sleep()

            tls = threading.local()

            def f():
                # Sleep a bit so that the thread is still running when
                # Py_Finalize() is called.
                random_sleep()
                tls.x = Sleeper()
                random_sleep()

            threading.Thread(target=f).start()
            random_sleep()
        r   r   rI  r+   rE  r  r  r  s        r   test_finalization_shutdownz&ThreadTests.test_finalization_shutdown  s<    4 (d33Cc"""""r   c                    t          j                    t          j                                                                                      fd}t          j        |          }|                     |j        d            |                                                                  |                     |	                                           |j        }| 
                    |                    d          d                                            |                     |                    t          j                  d           |                     |	                                           |                                 | 
                    |	                                           |                     |j                   |                                 d S )Nc                                                                                          t          j        d           d S )N{Gz?)r   r   rK   rL   finishstarteds   r   r   z'ThreadTests.test_tstate_lock.<locals>.fC  s9    OONNJtr   rj   r   r   F)r   allocate_lockr   r!   r@   assertIs_tstate_lockr   r   r   r   r   r   r   r   r   )r+   r   r   tstate_lockr{  r|  s       @@r   test_tstate_lockzThreadTests.test_tstate_lock=  s   '))&((	 	 	 	 	 	
 A&&&and+++				

%%% n,,Q,77??? 	++G4I+JJERRR 	

%%%&&&!.)))	r   c                 ~   t          j                    t          j                                                                                      fd}t          j        |          }|                                                                  |                     dt          |                                                      d}t          d          D ])}|t          |          v r nt          j        d           *|                     |t          |                     |                                 d S )Nc                  X                                                                        d S r5   )r   r   rz  s   r   r   z(ThreadTests.test_repr_stopped.<locals>.ff  s)    OONNr   rj   r|  stoppedi  ry  )r   r}  r   r!   r@   r   r   r   r   r   rK   rL   r   )r+   r   r   LOOKING_FORr   r{  r|  s        @@r   test_repr_stoppedzThreadTests.test_repr_stopped`  s*   '))&((	 	 	 	 	 	 A&&&				ia)))  s 	 	Ad1gg%%Jtk477+++	r   c                    t          dd          D ]}t          j        |          fdt          |          D             }|D ]}|                                 |D ]}|                                 fdt          |          D             }|D ]}|                                 |D ]}|                                 |                     t          j                   d S )Nr/   r   c                 D    g | ]}t          j        j                   S rj   )r!   r@   r   r   rF  bss     r   
<listcomp>z;ThreadTests.test_BoundedSemaphore_limit.<locals>.<listcomp>  9     . . . !'rz::: . . .r   c                 D    g | ]}t          j        j                   S r  )r!   r@   r   r  s     r   r  z;ThreadTests.test_BoundedSemaphore_limit.<locals>.<listcomp>  r  r   )r   r!   r   r   r   r   
ValueErrorr   )r+   limitr   r   r  s       @r   test_BoundedSemaphore_limitz'ThreadTests.test_BoundedSemaphore_limit{  s#   1b\\ 	6 	6E+E22B. . . . %e. . .G  				  . . . . %e. . .G  				  j"*5555	6 	6r   c                 t   fdd fdd _         t          j                    }t          j                   	 t	          j                   dd l}|                               t          d          D ]}              	 t          j        |           d S # t          j        |           w xY w)Nc                     S r5   r:   frameeventrw   
noop_traces      r   r  z9ThreadTests.test_frame_tstate_tracing.<locals>.noop_trace  	    r   c               3      K   	 dV  )Nr/   	generatorr:   r:   r   r   r  z8ThreadTests.test_frame_tstate_tracing.<locals>.generator  s      "!!!!"r   c                  X     j                       _         t           j                   S r5   )gennext)callbackr  s   r   r  z7ThreadTests.test_frame_tstate_tracing.<locals>.callback  s(    |#(y{{%%%r   r   rE   )r  r   gettracesettracer!   	_testcapicall_in_temporary_c_threadr   )r+   	old_tracer  r   r  r  r  s       @@@r   test_frame_tstate_tracingz%ThreadTests.test_frame_tstate_tracing  s    	 	 	 	 		" 	" 	"	& 	& 	& 	& 	& 	& LNN	Z   	$z*** 00::: a  



 L#####CL####s   A	B! !B7c                    fdt          j                    }	 t          j                   t          j                    }|                     |           t          j        |           d S # t          j        |           w xY w)Nc                     S r5   r:   r  s      r   r  z-ThreadTests.test_gettrace.<locals>.noop_trace  r  r   )r!   r  r  rk   )r+   r  
trace_funcr  s      @r   test_gettracezThreadTests.test_gettrace  s    	 	 	 	 	 &((		*z***"+--JZ
333y)))))Iy))))s   =A. .Bc                    d }t          j                    }	 t          j        |           |                     |t          j                               t          j        |           d S # t          j        |           w xY w)Nc                      d S r5   r:   r   s    r   fnz'ThreadTests.test_getprofile.<locals>.fn  r_   r   )r!   
getprofile
setprofilerk   )r+   r  old_profiles      r   test_getprofilezThreadTests.test_getprofile  s|    *,,	. $$$R!5!7!7888 -----I ----s   ;A) )A?c                    dD ]}|                      |          5  t          j                    }t          j        |j        |          }|                                 |j        }|s!|                     |t          j                   n | 	                    |t          j                   |
                                 |                                 | 	                    |t          j                   d d d            n# 1 swxY w Y   d S )N)FTr>  )rd   r   )r   r!   r   r@   r   r   r  r   _shutdown_locksr   r   r   )r+   r   r  rn   r  s        r   test_shutdown_lockszThreadTests.test_shutdown_locks  sH   # 	I 	IFV,, I I!))")FKKK $1 MMM+y/HIIII$$[)2KLLL 		   i.GHHH'I I I I I I I I I I I I I I I	I 	Is   CC==D	D	c                 ~    t          dd          \  }}}|                     |                                d           d S )Nr   a(  if 1:
            import threading

            class Atexit:
                def __del__(self):
                    print("thread_dict.atexit = %r" % thread_dict.atexit)

            thread_dict = threading.local()
            thread_dict.atexit = "value"

            atexit = Atexit()
        s   thread_dict.atexit = 'value')r	   rk   rC  r  s       r   test_locals_at_exitzThreadTests.test_locals_at_exit  sG     ( /  C 	'FGGGGGr   c                      G d dt                     } |            }t          j        |          }|                                 |                                 |                     |j                   d S )Nc                        e Zd Zd Zd Zd ZdS )6ThreadTests.test_boolean_target.<locals>.BooleanTargetc                     d| _         d S NFranr*   s    r   r,   z?ThreadTests.test_boolean_target.<locals>.BooleanTarget.__init__  s     r   c                     dS r  r:   r*   s    r   __bool__z?ThreadTests.test_boolean_target.<locals>.BooleanTarget.__bool__  s    ur   c                     d| _         d S )NTr  r*   s    r   __call__z?ThreadTests.test_boolean_target.<locals>.BooleanTarget.__call__  s    r   N)r7   r8   r9   r,   r  r  r:   r   r   BooleanTargetr    sA        ! ! !           r   r  rj   )rm   r!   r@   r   r   r   r  )r+   r  rd   rn   s       r   test_boolean_targetzThreadTests.test_boolean_target  s    
	  	  	  	  	 F 	  	  	  !000
#####r   c                     d }t          j                    5  t          j        |                                           d d d            d S # 1 swxY w Y   d S )Nc                      d S r5   r:   r:   r   r   noopz0ThreadTests.test_leak_without_join.<locals>.noop	  r_   r   rj   )r   r   r!   r@   r   )r+   r  s     r   test_leak_without_joinz"ThreadTests.test_leak_without_join  s     	/11 	2 	2D)))//111	2 	2 	2 	2 	2 	2 	2 	2 	2 	2 	2 	2 	2 	2 	2 	2 	2 	2s   (AAAzneed debug build (Py_DEBUG)c                 d    t          dddd          \  }}}d}|                     ||           d S )Nz	-Wdefaultr   pass1)PYTHONTHREADDEBUGs   DeprecationWarning: The threading debug (PYTHONTHREADDEBUG environment variable) is deprecated and will be removed in Python 3.12)r	   r   )r+   r  r  r  r!  s        r   test_debug_deprecationz"ThreadTests.test_debug_deprecation  sK     (T6:=? ? ?CC 	c3r   c                     t          j        d          }t          d|          \  }}}|                     |d           |                     |d           d S )Na  
            import _thread
            import sys

            event = _thread.allocate_lock()
            event.acquire()

            def import_threading():
                import threading
                event.release()

            if 'threading' in sys.modules:
                raise Exception('threading is already imported')

            _thread.start_new_thread(import_threading, ())

            # wait until the threading module is imported
            event.acquire()
            event.release()

            if 'threading' not in sys.modules:
                raise Exception('threading is not imported')

            # don't wait until the thread completes
        r   r   )rA  rB  r	   rk   ru  s        r   test_import_from_another_threadz+ThreadTests.test_import_from_another_thread  sc         2 (d33Cc"""c"""""r   N)F)9r7   r8   r9   maxDiffr   ro   r   r   r   r   r   r   r   r   r   r  r  r
  r  r)  r8  r<  r?  r   rG  rJ  rV  r]  r   
skipUnlessr   rQ  rf  ri  skipIfr   r   r   r   requires_forkrn  rp  rs  rv  r  r  r  r  r  r  r  r  r  r  Py_DEBUGr  r  r:   r   r   r[   r[   l   s       G= = \=4  6 D D \D". ". ".H( ( ( 	  	  	 	  	  	 # # #.U U Up< < <! ! !B  2# # #(0 0 0"N N NB& & &>) ) )" " " < < <6 # # #4 7 7 7(   XY//1JKK3 3 LK 32 XY//1JKK  LK @ X_S\%668MNNWXY//1JKK<7 <7 <7 LK  ON<7|P P P P5 5 5:!# !# !#F! ! !F  66 6 6$ %$ %$ \%$N
* 
* 
*. . . I I \I.H H H"$ $ $&2 2 2 X#@AA    BA # # # # #r   r[   c                       e Zd Zd Zd Zed             Zed             Z ej	        e
j        ev d          d             Zed             Zed             Zd	S )
ThreadJoinOnShutdownc                     d|z   }t          d|          \  }}}|                                                    dd          }|                     |d           d S )Na  if 1:
            import sys, os, time, threading

            # a thread, which waits for the main program to terminate
            def joiningfunc(mainthread):
                mainthread.join()
                print('end of thread')
                # stdout is fully buffered because not a tty, we have to flush
                # before exit.
                sys.stdout.flush()
        
r   r`  rh   zend of main
end of thread
ra  )r+   scriptr  r  r  re  s         r   _run_and_joinz"ThreadJoinOnShutdown._run_and_join<  sd    
 
 (f55Czz||##D"--=>>>>>r   c                 4    d}|                      |           d S )Nzif 1:
            import os
            t = threading.Thread(target=joiningfunc,
                                 args=(threading.current_thread(),))
            t.start()
            time.sleep(0.1)
            print('end of main')
            r  r+   r  s     r   test_1_join_on_shutdownz,ThreadJoinOnShutdown.test_1_join_on_shutdownM  s%     	6"""""r   c                 4    d}|                      |           d S )Na  if 1:
            from test import support

            childpid = os.fork()
            if childpid != 0:
                # parent process
                support.wait_process(childpid, exitcode=0)
                sys.exit(0)

            # child process
            t = threading.Thread(target=joiningfunc,
                                 args=(threading.current_thread(),))
            t.start()
            print('end of main')
            r  r  s     r   test_2_join_in_forked_processz2ThreadJoinOnShutdown.test_2_join_in_forked_processY  s%     	6"""""r   c                 4    d}|                      |           d S )Na  if 1:
            from test import support

            main_thread = threading.current_thread()
            def worker():
                childpid = os.fork()
                if childpid != 0:
                    # parent process
                    support.wait_process(childpid, exitcode=0)
                    sys.exit(0)

                # child process
                t = threading.Thread(target=joiningfunc,
                                     args=(main_thread,))
                print('end of main')
                t.start()
                t.join() # Should not block: main_thread is already stopped

            w = threading.Thread(target=worker)
            w.start()
            r  r  s     r   !test_3_join_in_forked_from_threadz6ThreadJoinOnShutdown.test_3_join_in_forked_from_threadm  s%    
* 	6"""""r   rj  c                 \    d}t          d|          \  }}}|                     |           d S )Na  if True:
            import os
            import random
            import sys
            import time
            import threading

            thread_has_run = set()

            def random_io():
                '''Loop for a while sleeping random tiny amounts and doing some I/O.'''
                import test.test_threading as mod
                while True:
                    with open(mod.__file__, 'rb') as in_f:
                        stuff = in_f.read(200)
                        with open(os.devnull, 'wb') as null_f:
                            null_f.write(stuff)
                            time.sleep(random.random() / 1995)
                    thread_has_run.add(threading.current_thread())

            def main():
                count = 0
                for _ in range(40):
                    new_thread = threading.Thread(target=random_io)
                    new_thread.daemon = True
                    new_thread.start()
                    count += 1
                while len(thread_has_run) < count:
                    time.sleep(0.001)
                # Trigger process shutdown
                sys.exit(0)

            main()
            r   r	   r   r+   r  r  r  r  s        r   test_4_daemon_threadsz*ThreadJoinOnShutdown.test_4_daemon_threads  s;    
!D (f55Cr   c                     d }g }t          d          D ]@}t          j        |          }|                    |           |                                 A|D ]}|                                 d S )Nc                      t          j                    } | dk    rt          j        | d           d S t          j        d           d S )Nr   2   rO  )rQ  rR  r   rT  rS  )rU  s    r   do_fork_and_waitzIThreadJoinOnShutdown.test_reinit_tls_after_fork.<locals>.do_fork_and_wait  sC    '))CQww$S2666666r      rj   )r   r!   r@   r   r   r   )r+   r  r   r   r   s        r   test_reinit_tls_after_forkz/ThreadJoinOnShutdown.test_reinit_tls_after_fork  s    
	 	 	 r 	 	A (8999ANN1GGIIII 	 	AFFHHHH	 	r   c                    g }t          d          D ]A}t          j        d           }|                    |           |                                 Bt          j                    }|dk    rNt          t          j	                              dk    rt          j
        d           n+t          j
        d           nt          j        |d           |D ]}|                                 d S )	Nr  c                  *    t          j        d          S )Ng333333?)rK   rL   r:   r   r   rx   zKThreadJoinOnShutdown.test_clear_threads_states_after_fork.<locals>.<lambda>  s    C r   rj   r   r/   3   4   rO  )r   r!   r@   r   r   rQ  rR  r   r   _current_framesrS  r   rT  r   )r+   r   r   r   rU  s        r   $test_clear_threads_states_after_forkz9ThreadJoinOnShutdown.test_clear_threads_states_after_fork  s    
 r 	 	A (@(@AAAANN1GGIIIIgii!883&(())Q.. r2222 	 	AFFHHHH	 	r   N)r7   r8   r9   r  r  r   r  r  r   r  r   r   r   r  r  r  r:   r   r   r  r  :  s        ? ? ?"
# 
# 
# # # #& # # #6 X_S\%668MNN' ' ON'R   ,     r   r  c                   6    e Zd Zd Zd Zd Zed             ZdS )SubinterpThreadingTestsc                 
   t          j                    \  }}|                     t           j        |           |                     t           j        |           t	          t           d          rt          j        |d           ||fS )Nset_blockingF)rQ  piper   closer   r  )r+   rws      r   r  zSubinterpThreadingTests.pipe  sj    wyy1!$$$!$$$2~&& 	&OAu%%%1vr   c                     |                                  \  }}t          j        d|fz            }t          j                            |          }|                     |d           |                     t          j        |d          d           d S )Na  
            import os
            import random
            import threading
            import time

            def random_sleep():
                seconds = random.random() * 0.010
                time.sleep(seconds)

            def f():
                # Sleep a bit so that the thread is still running when
                # Py_EndInterpreter is called.
                random_sleep()
                os.write(%d, b"x")

            threading.Thread(target=f).start()
            random_sleep()
        r   r/      x	r  rA  rB  r   r   run_in_subinterprk   rQ  readr+   r  r  rE  r   s        r   test_threads_joinz)SubinterpThreadingTests.test_threads_join  s     yy{{1  $ d%   & l++D11a   A-----r   c                     |                                  \  }}t          j        d|fz            }t          j                            |          }|                     |d           |                     t          j        |d          d           d S )Na  
            import os
            import random
            import threading
            import time

            def random_sleep():
                seconds = random.random() * 0.010
                time.sleep(seconds)

            class Sleeper:
                def __del__(self):
                    random_sleep()

            tls = threading.local()

            def f():
                # Sleep a bit so that the thread is still running when
                # Py_EndInterpreter is called.
                random_sleep()
                tls.x = Sleeper()
                os.write(%d, b"x")

            threading.Thread(target=f).start()
            random_sleep()
        r   r/   r  r  r  s        r   test_threads_join_2z+SubinterpThreadingTests.test_threads_join_2  s    
 yy{{1  2 d3   4 l++D11a   A-----r   c                     dt           j        j         d}d|d}t           j                                        5  t	          d|          \  }}}d d d            n# 1 swxY w Y   |                     d|                                           d S )Nzif 1:
            import os
            import threading
            import time

            def f():
                # Make sure the daemon thread is still running when
                # Py_EndInterpreter is called.
                time.sleep(zJ)
            threading.Thread(target=f, daemon=True).start()
            zKif 1:
            import _testcapi

            _testcapi.run_in_subinterp(z)
            r   z:Fatal Python error: Py_EndInterpreter: not the last thread)r   r   r   SuppressCrashReportr
   r   rb  )r+   subinterp_coder  r  r  r  s         r   test_daemon_threads_fatal_errorz7SubinterpThreadingTests.test_daemon_threads_fatal_error-  s    
 !L6
 
 
 ">>	$
 \--// 	? 	?0v>>LBS	? 	? 	? 	? 	? 	? 	? 	? 	? 	? 	? 	? 	? 	? 	? ,-0ZZ\\	; 	; 	; 	; 	;s   AA"AN)r7   r8   r9   r  r  r  r   r  r:   r   r   r  r    s]          . . .8#. #. #.J ; ; \; ; ;r   r  c                   p    e Zd Zd Zd Zd Zd Zd Z e            d             Z	d Z
d Zd	 Zd
 Zd ZdS )ThreadingExceptionTestsc                     t          j                    }|                                 |                     t          |j                   |                                 d S r5   )r!   r@   r   r   RuntimeErrorr   r+   rn   s     r   test_start_thread_againz/ThreadingExceptionTests.test_start_thread_againH  sF    !##,555r   c                 l    t          j                    }|                     t          |j                   d S r5   )r!   r   r   r  r   )r+   r   s     r   test_joining_current_threadz3ThreadingExceptionTests.test_joining_current_threadN  s/    "133,(;<<<<<r   c                 l    t          j                    }|                     t          |j                   d S r5   )r!   r@   r   r  r   r  s     r   test_joining_inactive_threadz4ThreadingExceptionTests.test_joining_inactive_threadR  s.    !##,44444r   c                     t          j                    }|                                 |                     t          t
          |dd           |                                 d S r:  )r!   r@   r   r   r  r    r   r  s     r   test_daemonize_active_threadz4ThreadingExceptionTests.test_daemonize_active_threadV  sJ    !##,4HHHr   c                 l    t          j                    }|                     t          |j                   d S r5   )r!   r   r   r  r   r   s     r   test_releasing_unacquired_lockz6ThreadingExceptionTests.test_releasing_unacquired_lock\  s-    ~,55555r   c                    d}d}t          j        t          j        d|gt           j        t           j                  }|                                \  }}|                                                    dd          }|                     |j	        dd|                                z              |                     ||           d S )	Na  if True:
            import threading

            def recurse():
                return recurse()

            def outer():
                try:
                    recurse()
                except RecursionError:
                    pass

            w = threading.Thread(target=outer)
            w.start()
            w.join()
            print('end of main thread')
            zend of main thread
r   )stdoutstderrr`  rh   r   zUnexpected error: )

subprocessPopenr   
executablePIPEcommunicaterb  rc  rk   
returncode)r+   r  expected_outputpr  r  re  s          r   test_recursion_limitz,ThreadingExceptionTests.test_recursion_limit`  s    " 1cndF;$.OJOM M M}}&&tR00q*>*PQQQ/////r   c                 6   d}t          d|          \  }}}|                     |d           |                                }|                     d|           |                     d|           |                     d|           |                     d|           d S )Na  if True:
            import threading
            import time

            running = False
            def run():
                global running
                running = True
                while running:
                    time.sleep(0.01)
                1/0
            t = threading.Thread(target=run)
            t.start()
            while not running:
                time.sleep(0.01)
            running = False
            t.join()
            r   r   Exception in thread"Traceback (most recent call last):ZeroDivisionErrorUnhandled exceptionr	   rk   rb  r   r   r  s        r   test_print_exceptionz,ThreadingExceptionTests.test_print_exception  s    $ (f55Cc"""jjll+S111:C@@@)3///.44444r   c                 6   d}t          d|          \  }}}|                     |d           |                                }|                     d|           |                     d|           |                     d|           |                     d|           d S )Na  if True:
            import sys
            import threading
            import time

            running = False
            def run():
                global running
                running = True
                while running:
                    time.sleep(0.01)
                1/0
            t = threading.Thread(target=run)
            t.start()
            while not running:
                time.sleep(0.01)
            sys.stderr = None
            running = False
            t.join()
            r   r   r  r   r!  r"  r#  r  s        r   %test_print_exception_stderr_is_none_1z=ThreadingExceptionTests.test_print_exception_stderr_is_none_1  s    ( (f55Cc"""jjll+S111:C@@@)3///.44444r   c                     d}t          d|          \  }}}|                     |d           |                     d|                                           d S )Na  if True:
            import sys
            import threading
            import time

            running = False
            def run():
                global running
                running = True
                while running:
                    time.sleep(0.01)
                1/0
            sys.stderr = None
            t = threading.Thread(target=run)
            t.start()
            while not running:
                time.sleep(0.01)
            running = False
            t.join()
            r   r   r"  )r	   rk   r   rb  r  s        r   %test_print_exception_stderr_is_none_2z=ThreadingExceptionTests.test_print_exception_stderr_is_none_2  s[    ( (f55Cc""".

=====r   c                 (   d  G fddt           j                  } |            }|                                 |                                 |                     |j                   |                     |j        t                     d |_        d S )Nc                        r5   r:   r:   r   r   
bare_raisezOThreadingExceptionTests.test_bare_raise_in_brand_new_thread.<locals>.bare_raise  s    r   c                       e Zd ZdZ fdZdS )OThreadingExceptionTests.test_bare_raise_in_brand_new_thread.<locals>.Issue27558Nc                 \    	               d S # t           $ r}|| _        Y d }~d S d }~ww xY wr5   )r   exc)r+   r/  r+  s     r   rO   zSThreadingExceptionTests.test_bare_raise_in_brand_new_thread.<locals>.Issue27558.run  sI    #JLLLLL  # # #"DHHHHHHH#s   
 
+&+)r7   r8   r9   r/  rO   )r+  s   r   
Issue27558r-    s3        C# # # # # # #r   r0  )r!   r@   r   r   r   r/  r   r  )r+   r0  rn   r+  s      @r   #test_bare_raise_in_brand_new_threadz;ThreadingExceptionTests.test_bare_raise_in_brand_new_thread  s    	 	 		# 	# 	# 	# 	# 	# 	#) 	# 	# 	# VZ(((fj,777


r   c                     d |                      t          j        t          j                   fdt	          d          D             }|D ]*}|                                 |                                 +d S )Nc                      t          t          j        dd          5 } |                     d           t	          j                     d d d            d S # 1 swxY w Y   d S )Nr  rh  )encoding )openr   TESTFNwrite	tracebackformat_stack)fps    r   modify_filezQThreadingExceptionTests.test_multithread_modify_file_noerror.<locals>.modify_file  s    i&g>>> )"&((() ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) )s   )AAAc                 :    g | ]}t          j                   S r  )r!   r@   )r   r   r<  s     r   r  zPThreadingExceptionTests.test_multithread_modify_file_noerror.<locals>.<listcomp>  s7     
 
 
 K000
 
 
r   r  )r   r   unlinkr7  r   r   r   )r+   r   r   r<  s      @r   $test_multithread_modify_file_noerrorz<ThreadingExceptionTests.test_multithread_modify_file_noerror  s    	) 	) 	)
 		()*:;;;
 
 
 
3ZZ
 
 
  	 	AGGIIIFFHHHH	 	r   N)r7   r8   r9   r	  r  r  r  r  r   r  r$  r&  r(  r1  r?  r:   r   r   r  r  E  s          > > >5 5 5  6 6 6 0 0 0>5 5 565 5 5:> > >2  *    r   r  c                       e Zd Zd ZdS )ThreadRunFailc                      t          d          )N
run failedr  r*   s    r   rO   zThreadRunFail.run  s    &&&r   Nr   r:   r   r   rA  rA    s#        ' ' ' ' 'r   rA  c                   \     e Zd Z fdZd Zej        d             Zd Zd Z	d Z
d Z xZS )ExceptHookTestsc                 f    t          |            t                                                       d S r5   )r$   superrU   )r+   	__class__s    r   rU   zExceptHookTests.setUp  s&    "4(((r   c                    t          j        d          5 }t          d          }|                                 |                                 d d d            n# 1 swxY w Y   |                                                                }|                     d|j         d|           |                     d|           |                     d|           |                     d|           d S )	Nr  excepthook threadr>   Exception in thread :
#Traceback (most recent call last):
z   raise ValueError("run failed")zValueError: run failed)	r   captured_outputrA  r   r   getvaluer	  r   r?   )r+   r  rn   s      r   test_excepthookzExceptHookTests.test_excepthook  s   $X.. 	&"(;<<<FLLNNNKKMMM	 	 	 	 	 	 	 	 	 	 	 	 	 	 	
 ""((**=V[===vFFF<fEEE8&AAA.77777   9AA!Ac                 d   t          j        d          5 }	 t          d          # t          $ rR}t	          j        g t          j                    d           }	 t	          j        |           d }n# d }w xY wY d }~nd }~ww xY w	 d d d            n# 1 swxY w Y   |	                                
                                }|                     dt	          j                     d|           |                     d|           |                     d|           |                     d|           d S )Nr  bugrL  rM  rN  z  raise ValueError("bug")zValueError: bug)r   rO  r  r   r!   ExceptHookArgsr   exc_infor   rP  r	  r   r   )r+   r  r/  r   s       r   test_excepthook_thread_Nonez+ExceptHookTests.test_excepthook_thread_None  s    $X.. 		 &  '''       /0G#,..0G$0GHH (...  DD4DKKKKDDDDD  		  		  		  		  		  		  		  		  		  		  		  		  		  		  		  ""((**GY-@-B-BGGGPPP<fEEE16:::'00000sI   B&
B)A=A1.A=1A55A=8B=BBBBc                 B    G d dt           j                  }t          j        d          5 } |            }|                                 |                                 d d d            n# 1 swxY w Y   |                     |                                d           d S )Nc                       e Zd Zd ZdS )4ExceptHookTests.test_system_exit.<locals>.ThreadExitc                 .    t          j        d           d S r.   )r   exitr*   s    r   rO   z8ExceptHookTests.test_system_exit.<locals>.ThreadExit.run$  s    r   Nr   r:   r   r   
ThreadExitrZ  #  s#            r   r]  r  rh   )r!   r@   r   rO  r   r   rk   rP  )r+   r]  r  rn   s       r   test_system_exitz ExceptHookTests.test_system_exit"  s    	 	 	 	 	) 	 	 	
 $X.. 	&Z\\FLLNNNKKMMM	 	 	 	 	 	 	 	 	 	 	 	 	 	 	
 	**B/////s   3A,,A03A0c                    d fd}	 t          j        t          d|          5  t                      }|                                 |                                 d d d            n# 1 swxY w Y   |                     j        t                     |                     t          j
                  d           |                     j        j
        j                   |                     j        |           d d S # d w xY w)Nc                     | d S r5   r:   )	hook_argsr   s    r   hookz4ExceptHookTests.test_custom_excepthook.<locals>.hook2  s    DDDr   r   rC  )r   	swap_attrr!   rA  r   r   rk   exc_typer  rr   	exc_valueexc_traceback__traceback__r~  rn   )r+   rb  rn   r   s      @r   test_custom_excepthookz&ExceptHookTests.test_custom_excepthook/  s9   	 	 	 	 		"9lDAA  &              
 T]J777S00,???T/1MNNNMM$+v... DDD4DKKKKs/   C? 7A(C? (A,,C? /A,0BC? ?Dc                 (   d }d fd}t          j        t          d|          5  t          j        t          d|          5  t          j        d          5 }t                      }|                                 |                                 d d d            n# 1 swxY w Y   d d d            n# 1 swxY w Y   d d d            n# 1 swxY w Y   |                     |	                                d           |                     d           d S )Nc                      t          d          )Nthreading_hook failedrD  r   s    r   threading_hookzCExceptHookTests.test_custom_excepthook_fail.<locals>.threading_hookE  s    4555r   c                 &    t          |          d S r5   rs   )rd  re  rf  err_strs      r   sys_hookz=ExceptHookTests.test_custom_excepthook_fail.<locals>.sys_hookJ  s    )nnGGGr   r   r  z#Exception in threading.excepthook:
rk  )
r   rc  r!   r   rO  rA  r   r   rk   rP  )r+   rl  ro  r  rn   rn  s        @r   test_custom_excepthook_failz+ExceptHookTests.test_custom_excepthook_failD  s   	6 	6 	6 	% 	% 	% 	% 	% y,GG 	 	sL(;;	 	$X..	28"__FLLNNNKKMMM	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	**?	A 	A 	A"9:::::sY   C	B27BB2BB2"B#B2&C	2B6	6C	9B6	:C		CCc                 d   d }d } |            }t          j        t          d|          5   |            }t          j        t          _         |            }d d d            n# 1 swxY w Y   |                     ||           |                     ||           |                     |d           d S )Nc                      t          j        d          5 } t          d          }|                                 |                                 d d d            n# 1 swxY w Y   |                                 S )Nr  rK  r>   )r   rO  rA  r   r   rP  )outputrn   s     r   
run_threadz<ExceptHookTests.test_original_excepthook.<locals>.run_threadZ  s    (22 f&,?@@@               ??$$$rR  c                 <    t          dt          j                   d S )NzRunning a thread failed)file)rI   r   r  r   s    r   rl  z@ExceptHookTests.test_original_excepthook.<locals>.threading_hooka  s    +#*======r   r   zRunning a thread failed
)r   rc  r!   r"   r   rk   r   )r+   rt  rl  default_outputcustom_hook_outputrecovered_outputs         r   test_original_excepthookz(ExceptHookTests.test_original_excepthookY  s   	% 	% 	%	> 	> 	> $y,GG 	, 	,!+#,#;I )z||	, 	, 	, 	, 	, 	, 	, 	, 	, 	, 	, 	, 	, 	, 	,
 	)9:::N,>???+-HIIIIIs   +A##A'*A')r7   r8   r9   rU   rQ  r   r   rW  r^  rh  rp  rz  __classcell__)rI  s   @r   rF  rF    s            
8 
8 
8 1 1 1(0 0 0  *; ; ;*J J J J J J Jr   rF  c                        e Zd Zd Zd Zd ZdS )
TimerTestsc                 x    t                               |            g | _        t          j                    | _        d S r5   )rQ   rU   callback_argsr!   r   callback_eventr*   s    r   rU   zTimerTests.setUpq  s4    4   'o//r   c                 ~   t          j        d| j                  }|                                 | j                                         |j                            d           d|j        d<   | j        	                                 t          j        d| j                  }|                                 | j                                         | 
                    t          | j                  d           | 
                    | j        di fdi fg           |                                 |                                 d S )Nry  blahbarfoorf   r:   )r!   Timer_callback_spyr   r  r   r   r   r  clearrk   r   r  r   )r+   timer1timer2s      r    test_init_immutable_default_argsz+TimerTests.test_init_immutable_default_argsv  s    t'9::  """6"""$e!!###t'9::  """T/00!444+r2hR-ABBBr   c                     | j                             |d d          |                                f           | j                                         d S r5   )r  r   copyr  r   )r+   r   r  s      r   r  zTimerTests._callback_spy  sI    !!47FKKMM":;;;!!!!!r   N)r7   r8   r9   rU   r  r  r:   r   r   r}  r}  o  sA        0 0 0
  "" " " " "r   r}  c                   .    e Zd Z eej                  ZdS )	LockTestsN)r7   r8   r9   staticmethodr!   r   locktyper:   r   r   r  r    s        |IN++HHHr   r  c                   .    e Zd Z eej                  ZdS )PyRLockTestsN)r7   r8   r9   r  r!   _PyRLockr  r:   r   r   r  r    s         |I.//HHHr   r  zRLock not implemented in Cc                   .    e Zd Z eej                  ZdS )CRLockTestsN)r7   r8   r9   r  r!   _CRLockr  r:   r   r   r  r    s         |I-..HHHr   r  c                   .    e Zd Z eej                  ZdS )
EventTestsN)r7   r8   r9   r  r!   r   	eventtyper:   r   r   r  r    s        Y_--IIIr   r  c                   4    e Zd Z eej                  Zd ZdS )ConditionAsRLockTestsc                 0    |                      d           d S )Nz,Condition does not expose _recursion_count())skipTestr*   s    r   test_recursion_countz*ConditionAsRLockTests.test_recursion_count  s    DEEEEEr   N)r7   r8   r9   r  r!   r2  r  r  r:   r   r   r  r    s:        |I/00HF F F F Fr   r  c                   .    e Zd Z eej                  ZdS )ConditionTestsN)r7   r8   r9   r  r!   r2  condtyper:   r   r   r  r    s         |I/00HHHr   r  c                   .    e Zd Z eej                  ZdS )SemaphoreTestsN)r7   r8   r9   r  r!   	Semaphoresemtyper:   r   r   r  r    s         l9.//GGGr   r  c                   .    e Zd Z eej                  ZdS )BoundedSemaphoreTestsN)r7   r8   r9   r  r!   r   r  r:   r   r   r  r    s         l9566GGGr   r  c                   .    e Zd Z eej                  ZdS )BarrierTestsN)r7   r8   r9   r  r!   Barrierbarriertyper:   r   r   r  r    s         ,y011KKKr   r  c                       e Zd Zd ZdS )MiscTestCasec                 n    t          |            dh}ddh}t          j        | t          d||           d S )Nr   r5  r4  )r!   r   )extranot_exported)r$   r   check__all__r!   )r+   r  r  s      r   test__all__zMiscTestCase.test__all__  sW    "4((('7T9.F#(|	E 	E 	E 	E 	E 	Er   N)r7   r8   r9   r  r:   r   r   r  r    s(        E E E E Er   r  c                   X    e Zd Zd Zd Zd Zd Zd Zd Zd Z	e
j        d             Zd	S )
InterruptMainTestsc                    d }t          j         ||          }|                     t           j         ||           |                     t                    5  t	          j                     d d d            d S # 1 swxY w Y   d S )Nc                     ddz   d S )Nr/   r   r:   )signumr  s     r   handlerzLInterruptMainTests.check_interrupt_main_with_signal_handler.<locals>.handler  s    aCCCCr   )signalr   r   r!  r   interrupt_main)r+   r  r  old_handlers       r   (check_interrupt_main_with_signal_handlerz;InterruptMainTests.check_interrupt_main_with_signal_handler  s    	 	 	 mFG44v{;;;011 	% 	%"$$$	% 	% 	% 	% 	% 	% 	% 	% 	% 	% 	% 	% 	% 	% 	% 	% 	% 	%s   A55A9<A9c                 Z   t          j        |          }	 t          j         |t           j                   t          j        |           t          j         |t           j                   t          j        |           t          j         ||           d S # t          j         ||           w xY wr5   )r  	getsignalSIG_IGNr   r  SIG_DFL)r+   r  r  s      r   check_interrupt_main_noerrorz/InterruptMainTests.check_interrupt_main_noerror  s    "6**		+M&&.111"6***M&&.111"6*** M&'*****FM&'****s   A&B B*c                    d }t          j        |          }|                     t                    5  |                                 |                                 d d d            n# 1 swxY w Y   |                                 d S )Nc                  ,    t          j                     d S r5   )r   r  r:   r   r   call_interruptzHInterruptMainTests.test_interrupt_main_subthread.<locals>.call_interrupt  s    "$$$$$r   rj   )r!   r@   r   KeyboardInterruptr   r   )r+   r  r   s      r   test_interrupt_main_subthreadz0InterruptMainTests.test_interrupt_main_subthread  s    	% 	% 	%N333011 	 	GGIIIFFHHH	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	
s   )A((A,/A,c                     |                      t                    5  t          j                     d d d            d S # 1 swxY w Y   d S r5   )r   r  r   r  r*   s    r   test_interrupt_main_mainthreadz1InterruptMainTests.test_interrupt_main_mainthread  s     011 	% 	%"$$$	% 	% 	% 	% 	% 	% 	% 	% 	% 	% 	% 	% 	% 	% 	% 	% 	% 	%s   <A A c                     |                      t          j                   |                      t          j                   d S r5   )r  r  SIGINTSIGTERMr*   s    r   'test_interrupt_main_with_signal_handlerz:InterruptMainTests.test_interrupt_main_with_signal_handler  s4    55fmDDD55fnEEEEEr   c                     |                      t          j                   |                      t          j                   d S r5   )r  r  r  r  r*   s    r   test_interrupt_main_noerrorz.InterruptMainTests.test_interrupt_main_noerror  s4    ))&-888))&.99999r   c                     |                      t          t          j        d           |                      t          t          j        t          j                   |                      t          t          j        d           d S )Nr   i@B )r   r  r   r  r  NSIGr*   s    r   "test_interrupt_main_invalid_signalz5InterruptMainTests.test_interrupt_main_invalid_signal  s[    *g&<bAAA*g&<fkJJJ*g&<gFFFFFr   c                    dg}dg}dg}d }t          j        ||||f          }|                                 |d         s		 |d         	d|d<   |                                 |                     |d                    d S )NTFc                 T    d}d| d<   |d         r|r|dz  }nd S 	 |d         d|d<   d S )Ni Tr   r/   r:   )r|  continterrupted
iterationss       r   workerzAInterruptMainTests.test_can_interrupt_tight_loops.<locals>.worker  sT    $JGAJq'  !OJJF q'  "KNNNr   r   r   )r!   r@   r   r   r   )r+   r  r|  r  r  r   s         r   test_can_interrupt_tight_loopsz1InterruptMainTests.test_can_interrupt_tight_loops  s    v'g		" 		" 		" F$0LMMM				!* 	 !* 	Q	A'''''r   N)r7   r8   r9   r  r  r  r  r  r  r  r   reap_threadsr  r:   r   r   r  r    s        % % %+ + +	 	 	% % %F F F: : :G G G
 "( ( #"( ( (r   r  c                        e Zd Zd Zd Zd ZdS )AtexitTestsc                     t          dd          \  }}}|                     |           |                     |                                d           d S )Nr   zif True:
            import threading

            def run_last():
                print('parrot')

            threading._register_atexit(run_last)
        s   parrot)r	   r   rk   r	  r  s       r   test_atexit_outputzAtexitTests.test_atexit_output  sX    ' /  C 	i00000r   c                 X    t          dd          \  }}}|                     |           d S )Nr   aN  if True:
            import threading
            from unittest.mock import Mock

            mock = Mock()
            threading._register_atexit(mock)
            mock.assert_not_called()
            # force early shutdown to ensure it was called once
            threading._shutdown()
            mock.assert_called_once()
        r  r  s       r   test_atexit_called_oncez#AtexitTests.test_atexit_called_once  s:    ' 
/ 
 
C 	r   c                     t          dd          \  }}}|                     |           |                     d|                                           d S )Nr   zif True:
            import threading

            def func():
                pass

            def run_last():
                threading._register_atexit(func)

            threading._register_atexit(run_last)
        z2RuntimeError: can't register atexit after shutdown)r	   r   r   rb  r  s       r   test_atexit_after_shutdownz&AtexitTests.test_atexit_after_shutdown$  sb     ( 
/ 
 
C 	J

	 	 	 	 	r   N)r7   r8   r9   r  r  r  r:   r   r   r  r    sA        1 1 1      r   r  __main__)@__doc__test.supportr   r   r   r   r   r   test.support.import_helperr   test.support.script_helperr	   r
   rH   r   r   r!   rK   r   r"  rQ  r  r  rA  r9  r   r   r   requires_working_threadingr   r   r  r   r$   rm   r&   r@   r<   TestCaserQ   r[   r  r  r  rA  rF  r}  r  
RLockTestsr  r  r  r  r  r  r  r  r  r  r  r  r  r7   r[  r:   r   r   <module>r     s        > > > > > > > > 9 9 9 9 9 9 9 9 9 9 4 4 4 4 4 4 N N N N N N N N  



         				                             +  +4 8 8 8 8 +  73*++  4 4 4    f   < < < < <! < < <B% % % % %8$ % % %K# K# K# K# K#, K# K# K#\f f f f f< f f fR_; _; _; _; _;l _; _; _;Do o o o ol o o od' ' ' ' 'I$ ' ' '
pJ pJ pJ pJ pJl pJ pJ pJf" " " " " " " "8, , , , ,
$ , , ,0 0 0 0 0:( 0 0 0 "d*,HII/ / / / /*' / / JI/. . . . .& . . .F F F F FJ1 F F F1 1 1 1 1Z. 1 1 10 0 0 0 0Z. 0 0 07 7 7 7 7J< 7 7 72 2 2 2 2:* 2 2 2E E E E E8$ E E EM( M( M( M( M(* M( M( M(`/ / / / /(# / / /d zHMOOOOO r   