o
    éT•jú  ã                   @   s�   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„ Zdd„ Z	dd„ Z
ejdd	d
„ƒZddd„Zejddd„ƒZG dd„ dƒZdS )é    N)Úsupportc                   C   s   t  ¡ tj ¡ fS ©N)Ú_threadÚ_countÚ	threadingÚ	_danglingÚcopy© r	   r	   ú4/usr/lib/python3.10/test/support/threading_helper.pyÚthreading_setup   s   r   c               
   G   sª   d}t |ƒD ]L}t ¡ tjf}|| kr d S |sGdt_|d }t d|d | d  › d|d › dt|ƒ› d�¡ |D ]
}t d	|›�¡ q:d }d }t	 
d
¡ t ¡  qd S )Néd   Té   z&threading_cleanup() failed to cleanup r   z threads (count: z, dangling: ú)zDangling thread: ç{®Gáz„?)Úranger   r   r   r   r   Úenvironment_alteredÚprint_warningÚlenÚtimeÚsleepÚ
gc_collect)Úoriginal_valuesÚ
_MAX_COUNTÚcountÚvaluesÚdangling_threadsÚthreadr	   r	   r
   Úthreading_cleanup   s,   ÿþ
ý

ër   c                    s   t  ˆ ¡‡ fdd„ƒ}|S )zƒUse this function when threads are being used.  This will
    ensure that the threads are cleaned up even when the test fails.
    c                     s$   t ƒ }z	ˆ | Ž W t|Ž  S t|Ž  w r   )r   r   )ÚargsÚkey©Úfuncr	   r
   Ú	decorator:   s   zreap_threads.<locals>.decorator)Ú	functoolsÚwraps)r!   r"   r	   r    r
   Úreap_threads6   s   r%   c                 c   s  � | du rt j} t ¡ }zCdV  W t ¡ }||  }	 t ¡ }||kr$dS t ¡ |krFt ¡ | }d|| › d|d›d|› d|› d�	}t|ƒ‚t d	¡ t  ¡  qt ¡ }||  }	 t ¡ }||krc	 w t ¡ |kr…t ¡ | }d|| › d|d›d|› d|› d�	}t|ƒ‚t d	¡ t  ¡  qY)
aH  
    bpo-31234: Context manager to wait until all threads created in the with
    statement exit.

    Use _thread.count() to check if threads exited. Indirectly, wait until
    threads exit the internal t_bootstrap() C function of the _thread module.

    threading_setup() and threading_cleanup() are designed to emit a warning
    if a test leaves running threads in the background. This context manager
    is designed to cleanup threads started by the _thread.start_new_thread()
    which doesn't allow to wait for thread exit, whereas thread.Thread has a
    join() method.
    NTz!wait_threads() failed to cleanup z threads after ú.1fz seconds (count: z, old count: r   r   )	r   ÚSHORT_TIMEOUTr   r   r   Ú	monotonicÚAssertionErrorr   r   )ÚtimeoutÚ	old_countÚ
start_timeÚdeadliner   ÚdtÚmsgr	   r	   r
   Úwait_threads_exitD   sZ   €ÿþþ
õþýÿþþ
õr0   c                 C   s:   |du rt j}|  |¡ |  ¡ rd|d›d�}t|ƒ‚dS )zcJoin a thread. Raise an AssertionError if the thread is still alive
    after timeout seconds.
    Nzfailed to join the thread in r&   z seconds)r   r'   ÚjoinÚis_aliver)   )r   r*   r/   r	   r	   r
   Újoin_threadi   s   
þr3   c                 c   s,  � dd l }t| ƒ} g }z™z| D ]}| ¡  | |¡ qW n   tjr/tdt| ƒt|ƒf ƒ ‚ d V  W zX|r:|ƒ  t 	¡ }t
ddƒD ]/}|d7 }|D ]}| t|t 	¡  dƒ¡ qKdd„ |D ƒ}|se ntjrrtd	t|ƒ|f ƒ qCW d
d„ |D ƒ}|r‹| tj¡ tdt|ƒ ƒ‚d S d
d„ |D ƒ}|r¤| tj¡ tdt|ƒ ƒ‚w zW|r«|ƒ  t 	¡ }t
ddƒD ]/}|d7 }|D ]}| t|t 	¡  dƒ¡ q¼dd„ |D ƒ}|sÖ ntjrãtd	t|ƒ|f ƒ q´W d
d„ |D ƒ}|rü| tj¡ tdt|ƒ ƒ‚w d
d„ |D ƒ}|�r| tj¡ tdt|ƒ ƒ‚w )Nr   z/Can't start %d threads, only %d threads startedr   é   é<   r   c                 S   ó   g | ]}|  ¡ r|‘qS r	   ©r2   ©Ú.0Útr	   r	   r
   Ú
<listcomp>Ž   ó    z!start_threads.<locals>.<listcomp>z7Unable to join %d threads during a period of %d minutesc                 S   r6   r	   r7   r8   r	   r	   r
   r;   •   r<   zUnable to join %d threads)ÚfaulthandlerÚlistÚstartÚappendr   ÚverboseÚprintr   r   r(   r   r1   ÚmaxÚdump_tracebackÚsysÚstdoutr)   )ÚthreadsÚunlockr=   Ústartedr:   Úendtimer*   r	   r	   r
   Ústart_threadsu   s„   €þÿ
ÿ€þÿî
ÿ€ýrK   c                   @   s0   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
S )Úcatch_threading_exceptiona  
    Context manager catching threading.Thread exception using
    threading.excepthook.

    Attributes set when an exception is caught:

    * exc_type
    * exc_value
    * exc_traceback
    * thread

    See threading.excepthook() documentation for these attributes.

    These attributes are deleted at the context manager exit.

    Usage:

        with threading_helper.catch_threading_exception() as cm:
            # code spawning a thread which raises an exception
            ...

            # check the thread exception, use cm attributes:
            # exc_type, exc_value, exc_traceback, thread
            ...

        # exc_type, exc_value, exc_traceback, thread attributes of cm no longer
        # exists at this point
        # (to avoid reference cycles)
    c                 C   s"   d | _ d | _d | _d | _d | _d S r   )Úexc_typeÚ	exc_valueÚexc_tracebackr   Ú	_old_hook©Úselfr	   r	   r
   Ú__init__º   s
   
z"catch_threading_exception.__init__c                 C   s$   |j | _ |j| _|j| _|j| _d S r   )rM   rN   rO   r   )rR   r   r	   r	   r
   Ú_hookÁ   s   zcatch_threading_exception._hookc                 C   s   t j| _| jt _| S r   )r   Ú
excepthookrP   rT   rQ   r	   r	   r
   Ú	__enter__Ç   s   z#catch_threading_exception.__enter__c                 G   s   | j t_| `| `| `| `d S r   )rP   r   rU   rM   rN   rO   r   )rR   Úexc_infor	   r	   r
   Ú__exit__Ì   s
   z"catch_threading_exception.__exit__N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__rS   rT   rV   rX   r	   r	   r	   r
   rL   ›   s    rL   r   )r   Ú
contextlibr#   rE   r   r   Útestr   r   r   r%   Úcontextmanagerr0   r3   rK   rL   r	   r	   r	   r
   Ú<module>   s     
$%