U
    k]eۿ                     @   s  d 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 ddlmZ ddlmZ dd	lmZ dd
lmZ ddlmZ ddlmZ ddlmZ ddlmZ dZe
jdkreddd ZG dd dejZG dd dej Z!G dd dej"ej#Z$G dd dej%Z&G dd dZ'dd Z(G d d! d!e'Z)G d"d# d#e)Z*G d$d% d%e)Z+G d&d' d'e'Z,G d(d) d)e'Z-G d*d+ d+ej.Z/eZ0e/Z1dS ),z2Selector event loop for Unix with signal handling.    N   )base_events)base_subprocess)	constants)
coroutines)events)
exceptions)futures)selector_events)tasks)
transports)logger)SelectorEventLoopAbstractChildWatcherSafeChildWatcherFastChildWatcherMultiLoopChildWatcherThreadedChildWatcherDefaultEventLoopPolicyZwin32z+Signals are not really supported on Windowsc                 C   s   dS )zDummy signal handler.N )signumframer   r   )/usr/lib/python3.8/asyncio/unix_events.py_sighandler_noop*   s    r   c                       s   e Zd ZdZd) fdd	Z fddZdd Zd	d
 Zdd Zdd Z	dd Z
d*ddZd+ddZd,ddZdd Zd-dddddddZd.dddddddd Zd!d" Zd#d$ Zd%d& Zd'd( Z  ZS )/_UnixSelectorEventLoopzdUnix event loop.

    Adds signal handling and UNIX Domain Socket support to SelectorEventLoop.
    Nc                    s   t  | i | _d S N)super__init___signal_handlers)selfselector	__class__r   r   r   5   s    z_UnixSelectorEventLoop.__init__c                    sZ   t    t s.t| jD ]}| | qn(| jrVtjd| dt	| d | j
  d S )NzClosing the loop z@ on interpreter shutdown stage, skipping signal handlers removalsource)r   closesysis_finalizinglistr   remove_signal_handlerwarningswarnResourceWarningclearr   sigr!   r   r   r%   9   s    
z_UnixSelectorEventLoop.closec                 C   s   |D ]}|sq|  | qd S r   )_handle_signal)r   datar   r   r   r   _process_self_dataG   s    z)_UnixSelectorEventLoop._process_self_datac                 G   sL  t |st |rtd| | |   zt| j	  W n2 t
tfk
rt } ztt|W 5 d}~X Y nX t||| d}|| j|< zt|t t|d W n tk
rF } zz| j|= | jsztd W n4 t
tfk
r } ztd| W 5 d}~X Y nX |jtjkr4td| dn W 5 d}~X Y nX dS )zAdd a handler for a signal.  UNIX only.

        Raise ValueError if the signal number is invalid or uncatchable.
        Raise RuntimeError if there is a problem setting up the handler.
        z3coroutines cannot be used with add_signal_handler()NFset_wakeup_fd(-1) failed: %ssig  cannot be caught)r   ZiscoroutineZiscoroutinefunction	TypeError_check_signalZ_check_closedsignalset_wakeup_fdZ_csockfileno
ValueErrorOSErrorRuntimeErrorstrr   ZHandler   r   siginterruptr   infoerrnoEINVAL)r   r/   callbackargsexchandleZnexcr   r   r   add_signal_handlerN   s2    


z)_UnixSelectorEventLoop.add_signal_handlerc                 C   s8   | j |}|dkrdS |jr*| | n
| | dS )z2Internal helper that is the actual signal handler.N)r   getZ
_cancelledr)   Z_add_callback_signalsafe)r   r/   rG   r   r   r   r0   {   s    z%_UnixSelectorEventLoop._handle_signalc              
   C   s   |  | z| j|= W n tk
r,   Y dS X |tjkr@tj}ntj}zt|| W nB tk
r } z$|jtj	krt
d| dn W 5 d}~X Y nX | jsztd W n2 ttfk
r } ztd| W 5 d}~X Y nX dS )zwRemove a handler for a signal.  UNIX only.

        Return True if a signal handler was removed, False if not.
        Fr5   r6   Nr3   r4   T)r8   r   KeyErrorr9   SIGINTdefault_int_handlerSIG_DFLr=   rB   rC   r>   r:   r<   r   rA   )r   r/   handlerrF   r   r   r   r)      s(    

z,_UnixSelectorEventLoop.remove_signal_handlerc                 C   s6   t |tstd||t kr2td| dS )zInternal helper to validate a signal.

        Raise ValueError if the signal number is invalid or uncatchable.
        Raise RuntimeError if there is a problem setting up the handler.
        zsig must be an int, not zinvalid signal number N)
isinstanceintr7   r9   valid_signalsr<   r.   r   r   r   r8      s    
z$_UnixSelectorEventLoop._check_signalc                 C   s   t | ||||S r   )_UnixReadPipeTransportr   pipeprotocolwaiterextrar   r   r   _make_read_pipe_transport   s    z0_UnixSelectorEventLoop._make_read_pipe_transportc                 C   s   t | ||||S r   )_UnixWritePipeTransportrS   r   r   r   _make_write_pipe_transport   s    z1_UnixSelectorEventLoop._make_write_pipe_transportc	              
      s   t  }
|
 std|  }t| |||||||f||d|	}|
| | j| z|I d H  W nD t	t
fk
r    Y n, tk
r   |  | I d H   Y nX W 5 Q R X |S )NzRasyncio.get_child_watcher() is not activated, subprocess support is not installed.)rV   rW   )r   get_child_watcher	is_activer>   create_future_UnixSubprocessTransportadd_child_handlerZget_pid_child_watcher_callback
SystemExitKeyboardInterruptBaseExceptionr%   Z_wait)r   rU   rE   shellstdinstdoutstderrbufsizerW   kwargswatcherrV   transpr   r   r   _make_subprocess_transport   s8    

    
 z1_UnixSelectorEventLoop._make_subprocess_transportc                 C   s   |  |j| d S r   )call_soon_threadsafeZ_process_exited)r   pid
returncoderk   r   r   r   r`      s    z._UnixSelectorEventLoop._child_watcher_callback)sslsockserver_hostnamessl_handshake_timeoutc          	         s   |d kst |tst|r,|d krLtdn |d k	r<td|d k	rLtd|d k	r|d k	rdtdt|}ttjtjd}z |	d | 
||I d H  W q   |   Y qX n@|d krtd|jtjks|jtjkrtd||	d | j|||||d	I d H \}}||fS )
Nz/you have to pass server_hostname when using sslz+server_hostname is only meaningful with ssl1ssl_handshake_timeout is only meaningful with ssl3path and sock can not be specified at the same timer   Fzno path and sock were specified.A UNIX Domain Stream Socket was expected, got )rs   )rO   r?   AssertionErrorr<   osfspathsocketAF_UNIXSOCK_STREAMsetblockingZsock_connectr%   familytypeZ_create_connection_transport)	r   protocol_factorypathrp   rq   rr   rs   	transportrU   r   r   r   create_unix_connection   sT    




   z-_UnixSelectorEventLoop.create_unix_connectiond   T)rq   backlogrp   rs   start_servingc             
      s  t |trtd|d k	r&|s&td|d k	rH|d k	r@tdt|}ttjtj}|d dkrz t	
t	|jrt| W nB tk
r   Y n0 tk
r } ztd|| W 5 d }~X Y nX z|| W nl tk
r0 }	 z8|  |	jtjkrd|d}
ttj|
d n W 5 d }	~	X Y n   |   Y nX n<|d krZtd	|jtjksv|jtjkrtd
||d t| |g||||}|r|  tjd| dI d H  |S )Nz*ssl argument must be an SSLContext or Nonert   ru   r   )r    z2Unable to check or remove stale UNIX socket %r: %rzAddress z is already in usez-path was not specified, and no sock specifiedrv   F)loop)rO   boolr7   r<   rx   ry   rz   r{   r|   statS_ISSOCKst_moderemoveFileNotFoundErrorr=   r   errorZbindr%   rB   Z
EADDRINUSEr~   r   r}   r   ZServerZ_start_servingr   sleep)r   r   r   rq   r   rp   rs   r   errrF   msgZserverr   r   r   create_unix_server  sn    


 



  z)_UnixSelectorEventLoop.create_unix_serverc              
      s   z
t j W n, tk
r6 } ztdW 5 d }~X Y nX z| }W n2 ttjfk
rv } ztdW 5 d }~X Y nX zt |j	}W n, t
k
r } ztdW 5 d }~X Y nX |r|n|}	|	sdS |  }
| |
d |||||	d |
I d H S )Nzos.sendfile() is not availableznot a regular filer   )rx   sendfileAttributeErrorr   SendfileNotAvailableErrorr;   ioUnsupportedOperationfstatst_sizer=   r]   _sock_sendfile_native_impl)r   rq   fileoffsetcountrF   r;   r   Zfsize	blocksizefutr   r   r   _sock_sendfile_nativeJ  s2    
   z,_UnixSelectorEventLoop._sock_sendfile_nativec	                 C   s,  |  }	|d k	r| | | r4| ||| d S |rd|| }|dkrd| ||| || d S zt|	|||}
W nD ttfk
r   |d kr| 	|| | 
|	| j||	||||||
 Y nb tk
rj } z|d k	r|jtjkrt|tk	rtdtj}||_|}|dkrBtd}| ||| || n| ||| || W 5 d }~X Y n ttfk
r    Y n tk
r } z| ||| || W 5 d }~X Y njX |
dkr| ||| || nD||
7 }||
7 }|d kr
| 	|| | 
|	| j||	||||||
 d S )Nr   zsocket is not connectedzos.sendfile call failed)r;   remove_writer	cancelled_sock_sendfile_update_fileposZ
set_resultrx   r   BlockingIOErrorInterruptedError_sock_add_cancellation_callbackZ
add_writerr   r=   rB   ZENOTCONNr   ConnectionError	__cause__r   r   Zset_exceptionra   rb   rc   )r   r   Zregistered_fdrq   r;   r   r   r   
total_sentfdZsentrF   new_excr   r   r   r   r   a  s    

     



 


     z1_UnixSelectorEventLoop._sock_sendfile_native_implc                 C   s   |dkrt ||t j d S Nr   )rx   lseekSEEK_SET)r   r;   r   r   r   r   r   r     s    z4_UnixSelectorEventLoop._sock_sendfile_update_fileposc                    s    fdd}| | d S )Nc                    s&   |   r" }|dkr" | d S )Nr3   )r   r;   r   )r   r   r   rq   r   r   cb  s    zB_UnixSelectorEventLoop._sock_add_cancellation_callback.<locals>.cb)Zadd_done_callback)r   r   rq   r   r   r   r   r     s    z6_UnixSelectorEventLoop._sock_add_cancellation_callback)N)NN)NN)N)N)N)__name__
__module____qualname____doc__r   r%   r2   rH   r0   r)   r8   rX   rZ   rl   r`   r   r   r   r   r   r   __classcell__r   r   r!   r   r   /   sH   -
   
  
 
  .   CFr   c                       s   e Zd ZdZd fdd	Zdd Zdd Zd	d
 Zdd Zdd Z	dd Z
dd Zdd ZejfddZdddZdd Zdd Z  ZS ) rR   i   Nc                    s   t  | || jd< || _|| _| | _|| _d| _d| _	t
| jj}t|st|st|sd | _d | _d | _tdt
| jd | j| jj|  | j| jj| j| j |d k	r| jtj|d  d S )NrT   Fz)Pipe transport is for pipes/sockets only.)r   r   _extra_loop_piper;   _fileno	_protocol_closing_pausedrx   r   r   r   S_ISFIFOr   S_ISCHRr<   set_blocking	call_soonconnection_made_add_reader_read_readyr	   _set_result_unless_cancelled)r   r   rT   rU   rV   rW   moder!   r   r   r     s:    


 
 z_UnixReadPipeTransport.__init__c                 C   s   | j jg}| jd kr |d n| jr0|d |d| j  t| jdd }| jd k	r|d k	rt	|| jt
j}|r|d q|d n | jd k	r|d n
|d dd	|S )
Nclosedclosingfd=	_selectorpollingidleopen<{}> )r"   r   r   appendr   r   getattrr   r
   _test_selector_event	selectorsZ
EVENT_READformatjoin)r   rA   r    r   r   r   r   __repr__  s(    


  

z_UnixReadPipeTransport.__repr__c              
   C   s   zt | j| j}W nD ttfk
r,   Y n tk
rX } z| |d W 5 d }~X Y n^X |rl| j	| nJ| j
 rtd|  d| _| j
| j | j
| jj | j
| jd  d S )Nz"Fatal read error on pipe transport%r was closed by peerT)rx   readr   max_sizer   r   r=   _fatal_errorr   Zdata_receivedr   	get_debugr   rA   r   _remove_readerr   Zeof_received_call_connection_lost)r   r1   rF   r   r   r   r     s    
z"_UnixReadPipeTransport._read_readyc                 C   s>   | j s| jrd S d| _| j| j | j r:td|  d S )NTz%r pauses reading)r   r   r   r   r   r   r   debugr   r   r   r   pause_reading  s    
z$_UnixReadPipeTransport.pause_readingc                 C   sB   | j s| jsd S d| _| j| j| j | j r>td|  d S )NFz%r resumes reading)	r   r   r   r   r   r   r   r   r   r   r   r   r   resume_reading  s    
z%_UnixReadPipeTransport.resume_readingc                 C   s
   || _ d S r   r   r   rU   r   r   r   set_protocol  s    z#_UnixReadPipeTransport.set_protocolc                 C   s   | j S r   r   r   r   r   r   get_protocol  s    z#_UnixReadPipeTransport.get_protocolc                 C   s   | j S r   r   r   r   r   r   
is_closing  s    z!_UnixReadPipeTransport.is_closingc                 C   s   | j s| d  d S r   )r   _closer   r   r   r   r%     s    z_UnixReadPipeTransport.closec                 C   s,   | j d k	r(|d| t| d | j   d S Nzunclosed transport r#   r   r,   r%   r   _warnr   r   r   __del__  s    
z_UnixReadPipeTransport.__del__Fatal error on pipe transportc                 C   sZ   t |tr4|jtjkr4| j rLtjd| |dd n| j||| | j	d | 
| d S Nz%r: %sTexc_info)message	exceptionr   rU   )rO   r=   rB   ZEIOr   r   r   r   call_exception_handlerr   r   r   rF   r   r   r   r   r     s    
z#_UnixReadPipeTransport._fatal_errorc                 C   s(   d| _ | j| j | j| j| d S NT)r   r   r   r   r   r   r   rF   r   r   r   r   -  s    z_UnixReadPipeTransport._closec                 C   s4   z| j| W 5 | j   d | _ d | _d | _X d S r   r   r%   r   r   Zconnection_lostr   r   r   r   r   2  s    
z,_UnixReadPipeTransport._call_connection_lost)NN)r   )r   r   r   r   r   r   r   r   r   r   r   r   r%   r*   r+   r   r   r   r   r   r   r   r!   r   rR     s   
rR   c                       s   e Zd Zd% fdd	Zdd Zdd Zdd	 Zd
d Zdd Zdd Z	dd Z
dd Zdd Zdd Zdd ZejfddZdd Zd&dd Zd'd!d"Zd#d$ Z  ZS )(rY   Nc           
         s   t  || || jd< || _| | _|| _t | _d| _	d| _
t| jj}t|}t|}t|}	|s|s|	sd | _d | _d | _tdt| jd | j| jj|  |	s|rtjds| j| jj| j| j |d k	r| jtj|d  d S )NrT   r   Fz?Pipe transport is only for pipes, sockets and character devicesZaix)r   r   r   r   r;   r   r   	bytearray_buffer
_conn_lostr   rx   r   r   r   r   r   r   r<   r   r   r   r   r&   platform
startswithr   r   r	   r   )
r   r   rT   rU   rV   rW   r   Zis_charZis_fifoZ	is_socketr!   r   r   r   ?  s:    




 
 z _UnixWritePipeTransport.__init__c                 C   s   | j jg}| jd kr |d n| jr0|d |d| j  t| jdd }| jd k	r|d k	rt	|| jt
j}|r|d n
|d |  }|d|  n | jd k	r|d n
|d d	d
|S )Nr   r   r   r   r   r   zbufsize=r   r   r   )r"   r   r   r   r   r   r   r   r
   r   r   ZEVENT_WRITEget_write_buffer_sizer   r   )r   rA   r    r   rh   r   r   r   r   d  s,    


  


z _UnixWritePipeTransport.__repr__c                 C   s
   t | jS r   )lenr   r   r   r   r   r   |  s    z-_UnixWritePipeTransport.get_write_buffer_sizec                 C   s6   | j  rtd|  | jr*| t  n|   d S )Nr   )r   r   r   rA   r   r   BrokenPipeErrorr   r   r   r   r     s
    
z#_UnixWritePipeTransport._read_readyc              
   C   sR  t |tttfstt|t |tr.t|}|s6d S | jsB| jrj| jtj	krXt
d |  jd7  _d S | js8zt| j|}W nt ttfk
r   d}Y nZ ttfk
r    Y nB tk
r } z$|  jd7  _| |d W Y d S d }~X Y nX |t|krd S |dkr&t||d  }| j| j| j |  j|7  _|   d S )Nz=pipe closed by peer or os.write(pipe, data) raised exception.r   r   #Fatal write error on pipe transport)rO   bytesr   
memoryviewrw   reprr   r   r   Z!LOG_THRESHOLD_FOR_CONNLOST_WRITESr   warningr   rx   writer   r   r   ra   rb   rc   r   r   r   Z_add_writer_write_readyZ_maybe_pause_protocol)r   r1   nrF   r   r   r   r    s8    


z_UnixWritePipeTransport.writec              
   C   s  | j stdzt| j| j }W n ttfk
r:   Y n ttfk
rR    Y n t	k
r } z6| j 
  |  jd7  _| j| j | |d W 5 d }~X Y nhX |t| j kr| j 
  | j| j |   | jr| j| j | d  d S |dkr| j d |= d S )NzData should not be emptyr   r  r   )r   rw   rx   r  r   r   r   ra   rb   rc   r-   r   r   _remove_writerr   r   Z_maybe_resume_protocolr   r   r   )r   r  rF   r   r   r   r    s,    



z$_UnixWritePipeTransport._write_readyc                 C   s   dS r   r   r   r   r   r   can_write_eof  s    z%_UnixWritePipeTransport.can_write_eofc                 C   sB   | j r
d S | jstd| _ | js>| j| j | j| jd  d S r   )	r   r   rw   r   r   r   r   r   r   r   r   r   r   	write_eof  s    
z!_UnixWritePipeTransport.write_eofc                 C   s
   || _ d S r   r   r   r   r   r   r     s    z$_UnixWritePipeTransport.set_protocolc                 C   s   | j S r   r   r   r   r   r   r     s    z$_UnixWritePipeTransport.get_protocolc                 C   s   | j S r   r   r   r   r   r   r     s    z"_UnixWritePipeTransport.is_closingc                 C   s   | j d k	r| js|   d S r   )r   r   r  r   r   r   r   r%     s    z_UnixWritePipeTransport.closec                 C   s,   | j d k	r(|d| t| d | j   d S r   r   r   r   r   r   r     s    
z_UnixWritePipeTransport.__del__c                 C   s   |  d  d S r   )r   r   r   r   r   abort  s    z_UnixWritePipeTransport.abortr   c                 C   sN   t |tr(| j r@tjd| |dd n| j||| | jd | | d S r   )	rO   r=   r   r   r   r   r   r   r   r   r   r   r   r     s    

z$_UnixWritePipeTransport._fatal_errorc                 C   sF   d| _ | jr| j| j | j  | j| j | j| j| d S r   )	r   r   r   r	  r   r-   r   r   r   r   r   r   r   r     s    
z_UnixWritePipeTransport._closec                 C   s4   z| j| W 5 | j   d | _ d | _d | _X d S r   r   r   r   r   r   r     s    
z-_UnixWritePipeTransport._call_connection_lost)NN)r   )N)r   r   r   r   r   r   r   r  r  r
  r  r   r   r   r%   r*   r+   r   r  r   r   r   r   r   r   r!   r   rY   <  s"   %	#	

rY   c                   @   s   e Zd Zdd ZdS )r^   c           	   	   K   s   d }|t jkrt \}}zPt j|f||||d|d|| _|d k	rh|  t| d|d| j_	d }W 5 |d k	r|  |  X d S )NF)rd   re   rf   rg   Zuniversal_newlinesrh   wb)	buffering)

subprocessPIPErz   Z
socketpairr%   Popen_procr   detachre   )	r   rE   rd   re   rf   rg   rh   ri   Zstdin_wr   r   r   _start  s.    
    z_UnixSubprocessTransport._startN)r   r   r   r  r   r   r   r   r^   	  s   r^   c                   @   sH   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	dd Z
dS )r   aH  Abstract base class for monitoring child processes.

    Objects derived from this class monitor a collection of subprocesses and
    report their termination or interruption by a signal.

    New callbacks are registered with .add_child_handler(). Starting a new
    process must be done within a 'with' block to allow the watcher to suspend
    its activity until the new process if fully registered (this is needed to
    prevent a race condition in some implementations).

    Example:
        with watcher:
            proc = subprocess.Popen("sleep 1")
            watcher.add_child_handler(proc.pid, callback)

    Notes:
        Implementations of this class must be thread-safe.

        Since child watcher objects may catch the SIGCHLD signal and call
        waitpid(-1), there should be only one active object per process.
    c                 G   s
   t  dS )a  Register a new child handler.

        Arrange for callback(pid, returncode, *args) to be called when
        process 'pid' terminates. Specifying another callback for the same
        process replaces the previous handler.

        Note: callback() must be thread-safe.
        NNotImplementedErrorr   rn   rD   rE   r   r   r   r_   9  s    	z&AbstractChildWatcher.add_child_handlerc                 C   s
   t  dS )zRemoves the handler for process 'pid'.

        The function returns True if the handler was successfully removed,
        False if there was nothing to remove.Nr  r   rn   r   r   r   remove_child_handlerD  s    z)AbstractChildWatcher.remove_child_handlerc                 C   s
   t  dS )zAttach the watcher to an event loop.

        If the watcher was previously attached to an event loop, then it is
        first detached before attaching to the new loop.

        Note: loop may be None.
        Nr  r   r   r   r   r   attach_loopL  s    z AbstractChildWatcher.attach_loopc                 C   s
   t  dS )zlClose the watcher.

        This must be called to make sure that any underlying resource is freed.
        Nr  r   r   r   r   r%   V  s    zAbstractChildWatcher.closec                 C   s
   t  dS )zReturn ``True`` if the watcher is active and is used by the event loop.

        Return True if the watcher is installed and ready to handle process exit
        notifications.

        Nr  r   r   r   r   r\   ]  s    zAbstractChildWatcher.is_activec                 C   s
   t  dS )zdEnter the watcher's context and allow starting new processes

        This function must return selfNr  r   r   r   r   	__enter__f  s    zAbstractChildWatcher.__enter__c                 C   s
   t  dS )zExit the watcher's contextNr  r   abcr   r   r   __exit__l  s    zAbstractChildWatcher.__exit__N)r   r   r   r   r_   r  r  r%   r\   r  r!  r   r   r   r   r   "  s   
	r   c                 C   s2   t | rt |  S t | r*t | S | S d S r   )rx   WIFSIGNALEDWTERMSIG	WIFEXITEDWEXITSTATUS)statusr   r   r   _compute_returncodeq  s
    


r'  c                   @   sD   e Zd Zdd Zdd Zdd Zdd Zd	d
 Zdd Zdd Z	dS )BaseChildWatcherc                 C   s   d | _ i | _d S r   )r   
_callbacksr   r   r   r   r     s    zBaseChildWatcher.__init__c                 C   s   |  d  d S r   )r  r   r   r   r   r%     s    zBaseChildWatcher.closec                 C   s   | j d k	o| j  S r   )r   Z
is_runningr   r   r   r   r\     s    zBaseChildWatcher.is_activec                 C   s
   t  d S r   r  )r   expected_pidr   r   r   _do_waitpid  s    zBaseChildWatcher._do_waitpidc                 C   s
   t  d S r   r  r   r   r   r   _do_waitpid_all  s    z BaseChildWatcher._do_waitpid_allc                 C   s~   |d kst |tjst| jd k	r<|d kr<| jr<tdt | jd k	rT| j	t
j || _|d k	rz|t
j| j |   d S )NzCA loop is being detached from a child watcher with pending handlers)rO   r   ZAbstractEventLooprw   r   r)  r*   r+   RuntimeWarningr)   r9   SIGCHLDrH   	_sig_chldr,  r  r   r   r   r    s    
zBaseChildWatcher.attach_loopc              
   C   s^   z|    W nL ttfk
r&    Y n4 tk
rX } z| jd|d W 5 d }~X Y nX d S )N$Unknown exception in SIGCHLD handler)r   r   )r,  ra   rb   rc   r   r   r   r   r   r   r/    s    zBaseChildWatcher._sig_chldN)
r   r   r   r   r%   r\   r+  r,  r  r/  r   r   r   r   r(    s   r(  c                       sP   e Zd ZdZ fddZdd Zdd Zdd	 Zd
d Zdd Z	dd Z
  ZS )r   ad  'Safe' child watcher implementation.

    This implementation avoids disrupting other code spawning processes by
    polling explicitly each process in the SIGCHLD handler instead of calling
    os.waitpid(-1).

    This is a safe solution but it has a significant overhead when handling a
    big number of children (O(n) each time SIGCHLD is raised)
    c                    s   | j   t   d S r   )r)  r-   r   r%   r   r!   r   r   r%     s    
zSafeChildWatcher.closec                 C   s   | S r   r   r   r   r   r   r    s    zSafeChildWatcher.__enter__c                 C   s   d S r   r   r  r   r   r   r!    s    zSafeChildWatcher.__exit__c                 G   s   ||f| j |< | | d S r   )r)  r+  r  r   r   r   r_     s    z"SafeChildWatcher.add_child_handlerc                 C   s*   z| j |= W dS  tk
r$   Y dS X d S NTFr)  rJ   r  r   r   r   r    s
    z%SafeChildWatcher.remove_child_handlerc                 C   s   t | jD ]}| | q
d S r   r(   r)  r+  r  r   r   r   r,    s    z SafeChildWatcher._do_waitpid_allc                 C   s   |dkst zt|tj\}}W n( tk
rJ   |}d}td| Y n.X |dkrXd S t|}| j	 rxt
d|| z| j|\}}W n. tk
r   | j	 rtjd|dd Y nX |||f|  d S )Nr      8Unknown child process pid %d, will report returncode 255$process %s exited with returncode %s'Child watcher got an unexpected pid: %rTr   )rw   rx   waitpidWNOHANGChildProcessErrorr   r  r'  r   r   r   r)  poprJ   )r   r*  rn   r&  ro   rD   rE   r   r   r   r+    s6    

 
 zSafeChildWatcher._do_waitpid)r   r   r   r   r%   r  r!  r_   r  r,  r+  r   r   r   r!   r   r     s   
r   c                       sT   e Zd ZdZ fddZ fddZdd Zdd	 Zd
d Zdd Z	dd Z
  ZS )r   aW  'Fast' child watcher implementation.

    This implementation reaps every terminated processes by calling
    os.waitpid(-1) directly, possibly breaking other code spawning processes
    and waiting for their termination.

    There is no noticeable overhead when handling a big number of children
    (O(1) each time a child terminates).
    c                    s$   t    t | _i | _d| _d S r   )r   r   	threadingZLock_lock_zombies_forksr   r!   r   r   r     s    

zFastChildWatcher.__init__c                    s"   | j   | j  t   d S r   )r)  r-   r>  r   r%   r   r!   r   r   r%     s    

zFastChildWatcher.closec              
   C   s0   | j   |  jd7  _| W  5 Q R  S Q R X d S )Nr   )r=  r?  r   r   r   r   r    s    zFastChildWatcher.__enter__c              	   C   s^   | j B |  jd8  _| js"| js0W 5 Q R  d S t| j}| j  W 5 Q R X td| d S )Nr   z5Caught subprocesses termination from unknown pids: %s)r=  r?  r>  r?   r-   r   r  )r   r  r  r   Zcollateral_victimsr   r   r   r!    s    
zFastChildWatcher.__exit__c              	   G   st   | j std| jF z| j|}W n. tk
rT   ||f| j|< Y W 5 Q R  d S X W 5 Q R X |||f|  d S )NzMust use the context manager)r?  rw   r=  r>  r;  rJ   r)  )r   rn   rD   rE   ro   r   r   r   r_   '  s    z"FastChildWatcher.add_child_handlerc                 C   s*   z| j |= W dS  tk
r$   Y dS X d S r1  r2  r  r   r   r   r  5  s
    z%FastChildWatcher.remove_child_handlerc              	   C   s   zt dt j\}}W n tk
r,   Y d S X |dkr:d S t|}| j z| j|\}}W nN tk
r   | j	r|| j
|< | j rtd|| Y W 5 Q R  q d }Y nX | j rtd|| W 5 Q R X |d krtd|| q |||f|  q d S )Nr3   r   z,unknown process %s exited with returncode %sr6  z8Caught subprocess termination from unknown pid: %d -> %d)rx   r8  r9  r:  r'  r=  r)  r;  rJ   r?  r>  r   r   r   r   r  )r   rn   r&  ro   rD   rE   r   r   r   r,  <  s@    

 

  z FastChildWatcher._do_waitpid_all)r   r   r   r   r   r%   r  r!  r_   r  r,  r   r   r   r!   r   r     s   	r   c                   @   sh   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	dd Z
dd Zdd Zdd Zdd ZdS )r   a~  A watcher that doesn't require running loop in the main thread.

    This implementation registers a SIGCHLD signal handler on
    instantiation (which may conflict with other code that
    install own handler for this signal).

    The solution is safe but it has a significant overhead when
    handling a big number of processes (*O(n)* each time a
    SIGCHLD is received).
    c                 C   s   i | _ d | _d S r   )r)  _saved_sighandlerr   r   r   r   r   z  s    zMultiLoopChildWatcher.__init__c                 C   s
   | j d k	S r   )r@  r   r   r   r   r\   ~  s    zMultiLoopChildWatcher.is_activec                 C   sT   | j   | jd krd S ttj}|| jkr:td nttj| j d | _d S )Nz+SIGCHLD handler was changed by outside code)	r)  r-   r@  r9   	getsignalr.  r/  r   r  )r   rN   r   r   r   r%     s    


zMultiLoopChildWatcher.closec                 C   s   | S r   r   r   r   r   r   r    s    zMultiLoopChildWatcher.__enter__c                 C   s   d S r   r   r   exc_typeZexc_valZexc_tbr   r   r   r!    s    zMultiLoopChildWatcher.__exit__c                 G   s&   t  }|||f| j|< | | d S r   )r   get_running_loopr)  r+  )r   rn   rD   rE   r   r   r   r   r_     s    z'MultiLoopChildWatcher.add_child_handlerc                 C   s*   z| j |= W dS  tk
r$   Y dS X d S r1  r2  r  r   r   r   r    s
    z*MultiLoopChildWatcher.remove_child_handlerc                 C   sN   | j d k	rd S ttj| j| _ | j d kr<td tj| _ ttjd d S )NzaPrevious SIGCHLD handler was set by non-Python code, restore to default handler on watcher close.F)r@  r9   r.  r/  r   r  rM   r@   r  r   r   r   r    s    


z!MultiLoopChildWatcher.attach_loopc                 C   s   t | jD ]}| | q
d S r   r3  r  r   r   r   r,    s    z%MultiLoopChildWatcher._do_waitpid_allc           	      C   s   |dkst zt|tj\}}W n, tk
rN   |}d}td| d}Y nX |dkr\d S t|}d}z| j	|\}}}W n$ t
k
r   tjd|dd Y nHX | rtd|| n.|r| rtd	|| |j|||f|  d S )
Nr   r4  r5  FTr7  r   %Loop %r that handles pid %r is closedr6  )rw   rx   r8  r9  r:  r   r  r'  r)  r;  rJ   	is_closedr   r   rm   )	r   r*  rn   r&  ro   Z	debug_logr   rD   rE   r   r   r   r+    s<    
  z!MultiLoopChildWatcher._do_waitpidc              	   C   sL   z|    W n: ttfk
r&    Y n" tk
rF   tjddd Y nX d S )Nr0  Tr   )r,  ra   rb   rc   r   r  )r   r   r   r   r   r   r/    s    zMultiLoopChildWatcher._sig_chldN)r   r   r   r   r   r\   r%   r  r!  r_   r  r  r,  r+  r/  r   r   r   r   r   g  s   %r   c                   @   sn   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	e
jfddZdd Zdd Zdd Zdd ZdS )r   aA  Threaded child watcher implementation.

    The watcher uses a thread per process
    for waiting for the process finish.

    It doesn't require subscription on POSIX signal
    but a thread creation is not free.

    The watcher has O(1) complexity, its performance doesn't depend
    on amount of spawn processes.
    c                 C   s   t d| _i | _d S r   )	itertoolsr   _pid_counter_threadsr   r   r   r   r     s    zThreadedChildWatcher.__init__c                 C   s   dS r   r   r   r   r   r   r\     s    zThreadedChildWatcher.is_activec                 C   s   |    d S r   )_join_threadsr   r   r   r   r%     s    zThreadedChildWatcher.closec                 C   s.   dd t | j D }|D ]}|  qdS )z%Internal: Join all non-daemon threadsc                 S   s   g | ]}|  r|js|qS r   )is_alivedaemon.0threadr   r   r   
<listcomp>  s     z6ThreadedChildWatcher._join_threads.<locals>.<listcomp>N)r(   rI  valuesr   )r   threadsrO  r   r   r   rJ    s    z"ThreadedChildWatcher._join_threadsc                 C   s   | S r   r   r   r   r   r   r    s    zThreadedChildWatcher.__enter__c                 C   s   d S r   r   rB  r   r   r   r!    s    zThreadedChildWatcher.__exit__c                 C   s6   dd t | j D }|r2|| j dt| d d S )Nc                 S   s   g | ]}|  r|qS r   )rK  rM  r   r   r   rP  	  s    z0ThreadedChildWatcher.__del__.<locals>.<listcomp>z0 has registered but not finished child processesr#   )r(   rI  rQ  r"   r,   )r   r   rR  r   r   r   r     s    zThreadedChildWatcher.__del__c                 G   sF   t  }tj| jdt| j ||||fdd}|| j|< |  d S )Nzwaitpid-T)targetnamerE   rL  )	r   rD  r<  ZThreadr+  nextrH  rI  start)r   rn   rD   rE   r   rO  r   r   r   r_     s    

z&ThreadedChildWatcher.add_child_handlerc                 C   s   dS r   r   r  r   r   r   r    s    z)ThreadedChildWatcher.remove_child_handlerc                 C   s   d S r   r   r  r   r   r   r    s    z ThreadedChildWatcher.attach_loopc                 C   s   |dkst zt|d\}}W n( tk
rH   |}d}td| Y n X t|}| rhtd|| |	 rtd|| n|j
|||f|  | j| d S )Nr   r4  r5  r6  rE  )rw   rx   r8  r:  r   r  r'  r   r   rF  rm   rI  r;  )r   r   r*  rD   rE   rn   r&  ro   r   r   r   r+  "  s(    
 z ThreadedChildWatcher._do_waitpidN)r   r   r   r   r   r\   r%   rJ  r  r!  r*   r+   r   r_   r  r  r+  r   r   r   r   r     s   	r   c                       sH   e Zd ZdZeZ fddZdd Z fddZdd	 Z	d
d Z
  ZS )_UnixDefaultEventLoopPolicyz:UNIX event loop policy with a watcher for child processes.c                    s   t    d | _d S r   )r   r   _watcherr   r!   r   r   r   A  s    
z$_UnixDefaultEventLoopPolicy.__init__c              	   C   sH   t j8 | jd kr:t | _tt tjr:| j| j	j
 W 5 Q R X d S r   )r   r=  rX  r   rO   r<  current_thread_MainThreadr  _localr   r   r   r   r   _init_watcherE  s    
z)_UnixDefaultEventLoopPolicy._init_watcherc                    s6   t  | | jdk	r2tt tjr2| j| dS )zSet the event loop.

        As a side effect, if a child watcher was set before, then calling
        .set_event_loop() from the main thread will call .attach_loop(loop) on
        the child watcher.
        N)r   set_event_looprX  rO   r<  rY  rZ  r  r  r!   r   r   r]  M  s
    
z*_UnixDefaultEventLoopPolicy.set_event_loopc                 C   s   | j dkr|   | j S )z~Get the watcher for child processes.

        If not yet set, a ThreadedChildWatcher object is automatically created.
        N)rX  r\  r   r   r   r   r[   [  s    
z-_UnixDefaultEventLoopPolicy.get_child_watcherc                 C   s4   |dkst |tst| jdk	r*| j  || _dS )z$Set the watcher for child processes.N)rO   r   rw   rX  r%   )r   rj   r   r   r   set_child_watchere  s    

z-_UnixDefaultEventLoopPolicy.set_child_watcher)r   r   r   r   r   Z_loop_factoryr   r\  r]  r[   r^  r   r   r   r!   r   rW  =  s   
rW  )2r   rB   r   rG  rx   r   r9   rz   r   r  r&   r<  r*    r   r   r   r   r   r   r	   r
   r   r   logr   __all__r   ImportErrorr   ZBaseSelectorEventLoopr   ZReadTransportrR   Z_FlowControlMixinZWriteTransportrY   ZBaseSubprocessTransportr^   r   r'  r(  r   r   r   r   ZBaseDefaultEventLoopPolicyrW  r   r   r   r   r   r   <module>   s`   	
    	 NO5Ji}Y3