o
    f                     @   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 )Nd   T   z&threading_cleanup() failed to cleanup r   z threads (count: z, dangling: )zDangling thread: {Gz?)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 )zUse 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rt | }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 }zz| 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 qdd |D }|s ntjrtd	t||f  qW 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     
$%