B
    18™\µ  ã               @   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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rêe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%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Z+e*Z,dS )%z2Selector event loop for Unix with signal handling.é    Né   )Úbase_events)Úbase_subprocess)Ú	constants)Ú
coroutines)Úevents)Úfutures)Úselector_events)Útasks)Ú
transports)Úlogger)ÚSelectorEventLoopÚAbstractChildWatcherÚSafeChildWatcherÚFastChildWatcherÚDefaultEventLoopPolicyÚwin32z+Signals are not really supported on Windowsc             C   s   dS )zDummy signal handler.N© )ÚsignumÚframer   r   úW/oak/stanford/groups/akundaje/marinovg/programs/Python-3.7.3/Lib/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   2   s    z_UnixSelectorEventLoop.__init__c                s^   t ƒ  ¡  t ¡ s2xFt| jƒD ]}|  |¡ qW n(| jrZt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   Úsig)r   r   r   r    6   s    
z_UnixSelectorEventLoop.closec             C   s"   x|D ]}|sq|   |¡ qW d S )N)Ú_handle_signal)r   Údatar   r   r   r   Ú_process_self_dataD   s    
z)_UnixSelectorEventLoop._process_self_datac             G   sL  t  |¡st  |¡rtdƒ‚|  |¡ |  ¡  yt | j 	¡ ¡ W n2 t
tfk
rt } ztt|ƒƒ‚W dd}~X Y nX t ||| d¡}|| j|< yt |t¡ t |d¡ W nš tk
rF } zz| j|= | jsyt d¡ W n4 t
tfk
r } zt d|¡ W dd}~X Y nX |jtjkr4td|› dƒ‚n‚ W dd}~X Y nX dS )zÃAdd 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éÿÿÿÿzset_wakeup_fd(-1) failed: %szsig z cannot be caught)r   ÚiscoroutineÚiscoroutinefunctionÚ	TypeErrorÚ_check_signalÚ_check_closedÚsignalÚset_wakeup_fdZ_csockÚfilenoÚ
ValueErrorÚOSErrorÚRuntimeErrorÚstrr   ÚHandler   r   Úsiginterruptr   ÚinfoÚerrnoÚEINVAL)r   r)   ÚcallbackÚargsÚexcÚhandleZnexcr   r   r   Úadd_signal_handlerK   s0    



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   ÚgetÚ
_cancelledr$   Ú_add_callback_signalsafe)r   r)   rB   r   r   r   r*   x   s    z%_UnixSelectorEventLoop._handle_signalc          
   C   sä   |   |¡ y| j|= W n tk
r*   dS X |tjkr>tj}ntj}yt ||¡ W nB tk
r– } z$|jtj	kr„t
d|› dƒ‚n‚ W dd}~X Y nX | jsàyt d¡ W n2 ttfk
rÞ } zt d|¡ W d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.
        Fzsig z cannot be caughtNr-   zset_wakeup_fd(-1) failed: %sT)r1   r   ÚKeyErrorr3   ÚSIGINTÚdefault_int_handlerÚSIG_DFLr7   r=   r>   r8   r4   r6   r   r<   )r   r)   ÚhandlerrA   r   r   r   r$   ‚   s(    

z,_UnixSelectorEventLoop.remove_signal_handlerc             C   sL   t |tƒstd|›ƒ‚d|  kr.tjk sHn td|› dtj› dƒ‚dS )zÁInternal 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 r   zsig z out of range(1, ú)N)Ú
isinstanceÚintr0   r3   ÚNSIGr6   )r   r)   r   r   r   r1   ¢   s    
z$_UnixSelectorEventLoop._check_signalc             C   s   t | ||||ƒS )N)Ú_UnixReadPipeTransport)r   ÚpipeÚprotocolÚwaiterÚextrar   r   r   Ú_make_read_pipe_transport®   s    z0_UnixSelectorEventLoop._make_read_pipe_transportc             C   s   t | ||||ƒS )N)Ú_UnixWritePipeTransport)r   rQ   rR   rS   rT   r   r   r   Ú_make_write_pipe_transport²   s    z1_UnixSelectorEventLoop._make_write_pipe_transportc	          
   Ë   s”   t  ¡ ‚}
|  ¡ }t| |||||||f||dœ|	—Ž}|
 | ¡ | j|¡ y|I d H  W n, tk
r„   | ¡  | 	¡ I d H  ‚ Y nX W d Q R X |S )N)rS   rT   )
r   Úget_child_watcherÚcreate_futureÚ_UnixSubprocessTransportÚadd_child_handlerÚget_pidÚ_child_watcher_callbackÚ	Exceptionr    Ú_wait)r   rR   r@   ÚshellÚstdinÚstdoutÚstderrÚbufsizerT   ÚkwargsÚwatcherrS   Útranspr   r   r   Ú_make_subprocess_transport¶   s    




z1_UnixSelectorEventLoop._make_subprocess_transportc             C   s   |   |j|¡ d S )N)Úcall_soon_threadsafeÚ_process_exited)r   ÚpidÚ
returncoderg   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¡}y | 	d¡ |  
||¡I d H  W qú   | ¡  ‚ Y qúX n@|d krÊtdƒ‚|jtjksâ|jtjkrðt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 sslz1ssl_handshake_timeout is only meaningful with sslz3path and sock can not be specified at the same timer   Fzno path and sock were specifiedz.A UNIX Domain Stream Socket was expected, got )rp   )rM   r9   ÚAssertionErrorr6   ÚosÚfspathÚsocketÚAF_UNIXÚSOCK_STREAMÚsetblockingÚsock_connectr    ÚfamilyÚtypeÚ_create_connection_transport)	r   Úprotocol_factoryÚpathrm   rn   ro   rp   Ú	transportrR   r   r   r   Úcreate_unix_connectionÎ   sB    



z-_UnixSelectorEventLoop.create_unix_connectionéd   T)rn   Úbacklogrm   rp   Ú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rÊy t	 
t 	|¡j¡r„t |¡ W nB tk
rš   Y n0 tk
rÈ } zt d||¡ W d d }~X Y nX y| |¡ W nl tk
r0 }	 z8| ¡  |	jtjkrd|›d}
ttj|
ƒd ‚n‚ W d d }	~	X Y n   | ¡  ‚ Y nX n<|d krZtd	ƒ‚|jtjksv|jtjkr„td
|›ƒ‚| d¡ t | |g||||¡}|rÆ| ¡  tjd| dI d H  |S )Nz*ssl argument must be an SSLContext or Nonez1ssl_handshake_timeout is only meaningful with sslz3path and sock can not be specified at the same timer   )r   ú z2Unable to check or remove stale UNIX socket %r: %rzAddress z is already in usez-path was not specified, and no sock specifiedz.A UNIX Domain Stream Socket was expected, got F)Úloop)rM   Úboolr0   r6   rr   rs   rt   ru   rv   ÚstatÚS_ISSOCKÚst_modeÚremoveÚFileNotFoundErrorr7   r   ÚerrorÚbindr    r=   Z
EADDRINUSEry   rz   rw   r   ÚServerÚ_start_servingr
   Úsleep)r   r|   r}   rn   r   rm   rp   r‚   ÚerrrA   ÚmsgÚserverr   r   r   Úcreate_unix_serverû   sZ    






z)_UnixSelectorEventLoop.create_unix_serverc          
   Ã   sô   y
t j W n, tk
r6 } zt d¡‚W d d }~X Y nX y| ¡ }W n2 ttjfk
rv } zt d¡‚W d d }~X Y nX yt  |¡j	}W n, t
k
r´ } zt d¡‚W d d }~X Y nX |r¾|n|}	|	sÊdS |  ¡ }
|  |
d |||||	d¡ |
I d H S )Nzos.sendfile() is not availableznot a regular filer   )rr   ÚsendfileÚAttributeErrorr   ÚSendfileNotAvailableErrorr5   ÚioÚUnsupportedOperationÚfstatÚst_sizer7   rY   Ú_sock_sendfile_native_impl)r   rn   ÚfileÚoffsetÚcountrA   r5   r   ÚfsizeÚ	blocksizeÚfutr   r   r   Ú_sock_sendfile_native>  s(    
z,_UnixSelectorEventLoop._sock_sendfile_nativec	             C   s  |  ¡ }	|d k	r|  |¡ | ¡ r4|  |||¡ d S |rd|| }|dkrd|  |||¡ | |¡ d S yt |	|||¡}
W n* ttfk
rÆ   |d kr¢|  	||¡ |  
|	| j||	||||||¡
 Y nH 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 d d }~X Y n¤ tk
r¤ } z|  |||¡ | |¡ W d 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)r5   Úremove_writerÚ	cancelledÚ_sock_sendfile_update_fileposÚ
set_resultrr   r”   ÚBlockingIOErrorÚInterruptedErrorÚ_sock_add_cancellation_callbackÚ
add_writerr›   r7   r=   ZENOTCONNrz   ÚConnectionErrorÚ	__cause__r   r–   Úset_exceptionr^   )r   r¡   Zregistered_fdrn   r5   r   rž   r    Ú
total_sentÚfdÚsentrA   Únew_excr   r   r   r   r›   U  s`    






z1_UnixSelectorEventLoop._sock_sendfile_native_implc             C   s   |dkrt  ||t j¡ d S )Nr   )rr   ÚlseekÚSEEK_SET)r   r5   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 )Nr-   )r¤   r5   r£   )r¡   r¯   )r   rn   r   r   Úcbž  s    zB_UnixSelectorEventLoop._sock_add_cancellation_callback.<locals>.cb)Úadd_done_callback)r   r¡   rn   r´   r   )r   rn   r   r©     s    z6_UnixSelectorEventLoop._sock_add_cancellation_callback)N)NN)NN)N)N)N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r    r,   rC   r*   r$   r1   rU   rW   rh   r]   r   r“   r¢   r›   r¥   r©   Ú__classcell__r   r   )r   r   r   ,   s4   -
  
 

*?D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dd„ Zddd„Zdd„ Zdd„ Z‡  ZS ) rP   i   Nc                sÔ   t ƒ  |¡ || jd< || _|| _| ¡ | _|| _d| _t	 
| j¡j}t |¡s~t |¡s~t |¡s~d | _d | _d | _tdƒ‚t	 | jd¡ | j | jj| ¡ | j | jj| j| j¡ |d k	rÐ| j tj|d ¡ d S )NrQ   Fz)Pipe transport is for pipes/sockets only.)r   r   Ú_extraÚ_loopÚ_piper5   Ú_filenoÚ	_protocolÚ_closingrr   r™   rˆ   r†   ÚS_ISFIFOr‡   ÚS_ISCHRr6   Úset_blockingÚ	call_soonÚconnection_madeÚ_add_readerÚ_read_readyr   Ú_set_result_unless_cancelled)r   r„   rQ   rR   rS   rT   Úmode)r   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Úclosingzfd=Ú	_selectorÚpollingÚidleÚopenz<{}>ú )r   r¶   r½   ÚappendrÀ   r¾   Úgetattrr¼   r	   Ú_test_selector_eventÚ	selectorsÚ
EVENT_READÚformatÚjoin)r   r<   r   rÍ   r   r   r   Ú__repr__Ç  s"    




z_UnixReadPipeTransport.__repr__c          
   C   sº   yt  | j| j¡}W nD ttfk
r,   Y nŠ tk
rX } z|  |d¡ W d d }~X Y n^X |rl| j 	|¡ nJ| j
 ¡ r‚t d| ¡ d| _| j
 | j¡ | j
 | jj¡ | j
 | jd ¡ d S )Nz"Fatal read error on pipe transportz%r was closed by peerT)rr   Úreadr¾   Úmax_sizer§   r¨   r7   Ú_fatal_errorr¿   Údata_receivedr¼   Ú	get_debugr   r<   rÀ   Ú_remove_readerrÄ   Úeof_receivedÚ_call_connection_lost)r   r+   rA   r   r   r   rÇ   Ü  s    
z"_UnixReadPipeTransport._read_readyc             C   s   | j  | j¡ d S )N)r¼   rÞ   r¾   )r   r   r   r   Úpause_readingî  s    z$_UnixReadPipeTransport.pause_readingc             C   s   | j  | j| j¡ d S )N)r¼   rÆ   r¾   rÇ   )r   r   r   r   Úresume_readingñ  s    z%_UnixReadPipeTransport.resume_readingc             C   s
   || _ d S )N)r¿   )r   rR   r   r   r   Úset_protocolô  s    z#_UnixReadPipeTransport.set_protocolc             C   s   | j S )N)r¿   )r   r   r   r   Úget_protocol÷  s    z#_UnixReadPipeTransport.get_protocolc             C   s   | j S )N)rÀ   )r   r   r   r   Ú
is_closingú  s    z!_UnixReadPipeTransport.is_closingc             C   s   | j s|  d ¡ d S )N)rÀ   Ú_close)r   r   r   r   r    ý  s    z_UnixReadPipeTransport.closec             C   s.   | j d k	r*tjd| ›t| d | j  ¡  d S )Nzunclosed transport )r   )r½   r%   r&   r'   r    )r   r   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~   rR   )rM   r7   r=   ZEIOr¼   rÝ   r   ÚdebugÚcall_exception_handlerr¿   ræ   )r   rA   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   rA   r   r   r   ræ     s    z_UnixReadPipeTransport._closec             C   s4   z| j  |¡ W d | j ¡  d | _d | _ d | _X d S )N)r¿   Úconnection_lostr½   r    r¼   )r   rA   r   r   r   rà     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   rP   ¦  s   
rP   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dd„ Zdd„ Zd&dd „Zd'd!d"„Zd#d$„ Z‡  ZS )(rV   Nc       
         sþ   t ƒ  ||¡ || jd< || _| ¡ | _|| _tƒ | _d| _	d| _
t | j¡j}t |¡}t |¡}t |¡}	|s”|s”|	s”d | _d | _d | _tdƒ‚t | jd¡ | j | jj| ¡ |	sÈ|ràtj d¡sà| j | jj| j| j¡ |d k	rú| j tj|d ¡ d S )NrQ   r   Fz?Pipe transport is only for pipes, sockets and character devicesÚaix)r   r   r»   r½   r5   r¾   r¿   Ú	bytearrayÚ_bufferÚ
_conn_lostrÀ   rr   r™   rˆ   r†   rÂ   rÁ   r‡   r6   rÃ   r¼   rÄ   rÅ   r!   ÚplatformÚ
startswithrÆ   rÇ   r   rÈ   )
r   r„   rQ   rR   rS   rT   rÉ   Zis_charZis_fifoZ	is_socket)r   r   r   r   '  s2    





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	r¨t 	|| jt
j¡}|r„| d¡ n
| d¡ |  ¡ }| d|› ¡ n | jd k	r¾| d¡ n
| d¡ d	 d
 |¡¡S )NrÊ   rË   zfd=rÌ   rÍ   rÎ   zbufsize=rÏ   z<{}>rÐ   )r   r¶   r½   rÑ   rÀ   r¾   rÒ   r¼   r	   rÓ   rÔ   ÚEVENT_WRITEÚget_write_buffer_sizerÖ   r×   )r   r<   r   rÍ   rd   r   r   r   rØ   L  s&    





z _UnixWritePipeTransport.__repr__c             C   s
   t | jƒS )N)Úlenrñ   )r   r   r   r   rö   d  s    z-_UnixWritePipeTransport.get_write_buffer_sizec             C   s6   | j  ¡ rt d| ¡ | jr*|  tƒ ¡ n|  ¡  d S )Nz%r was closed by peer)r¼   rÝ   r   r<   rñ   ræ   ÚBrokenPipeError)r   r   r   r   rÇ   g  s
    
z#_UnixWritePipeTransport._read_readyc          
   C   s2  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syt | j|¡}W nV ttfk
r    d}Y n< tk
rÚ } z|  jd7  _|  |d¡ 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   z#Fatal write error on pipe transport)rM   Úbytesrð   Ú
memoryviewrq   Úreprrò   rÀ   r   Ú!LOG_THRESHOLD_FOR_CONNLOST_WRITESr   Úwarningrñ   rr   Úwriter¾   r§   r¨   r^   rÛ   r÷   r¼   Z_add_writerÚ_write_readyÚ_maybe_pause_protocol)r   r+   ÚnrA   r   r   r   rþ   p  s4    


z_UnixWritePipeTransport.writec          
   C   sö   | j stdƒ‚yt | j| j ¡}W nj ttfk
r:   Y n¸ tk
rŒ } z6| j  ¡  |  j	d7  _	| j
 | j¡ |  |d¡ W d d }~X Y nfX |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   z#Fatal write error on pipe transportr   )rñ   rq   rr   rþ   r¾   r§   r¨   r^   r(   rò   r¼   Ú_remove_writerrÛ   r÷   Ú_maybe_resume_protocolrÀ   rÞ   rà   )r   r  rA   r   r   r   rÿ   ‘  s(    


z$_UnixWritePipeTransport._write_readyc             C   s   dS )NTr   )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 )NT)	rÀ   r½   rq   rñ   r¼   rÞ   r¾   rÄ   rà   )r   r   r   r   Ú	write_eof®  s    
z!_UnixWritePipeTransport.write_eofc             C   s
   || _ d S )N)r¿   )r   rR   r   r   r   rã   ·  s    z$_UnixWritePipeTransport.set_protocolc             C   s   | j S )N)r¿   )r   r   r   r   rä   º  s    z$_UnixWritePipeTransport.get_protocolc             C   s   | j S )N)rÀ   )r   r   r   r   rå   ½  s    z"_UnixWritePipeTransport.is_closingc             C   s   | j d k	r| js|  ¡  d S )N)r½   rÀ   r  )r   r   r   r   r    À  s    z_UnixWritePipeTransport.closec             C   s.   | j d k	r*tjd| ›t| d | j  ¡  d S )Nzunclosed transport )r   )r½   r%   r&   r'   r    )r   r   r   r   rç   Å  s    
z_UnixWritePipeTransport.__del__c             C   s   |   d ¡ d S )N)ræ   )r   r   r   r   ÚabortË  s    z_UnixWritePipeTransport.abortúFatal error on pipe transportc             C   sP   t |tjƒr*| j ¡ rBtjd| |dd n| j ||| | jdœ¡ |  	|¡ d S )Nz%r: %sT)ré   )rê   rë   r~   rR   )
rM   r   Ú_FATAL_ERROR_IGNOREr¼   rÝ   r   rì   rí   r¿   ræ   )r   rA   rê   r   r   r   rÛ   Î  s    
z$_UnixWritePipeTransport._fatal_errorc             C   sF   d| _ | jr| j | j¡ | j ¡  | j | j¡ | j | j|¡ d S )NT)	rÀ   rñ   r¼   r  r¾   r(   rÞ   rÄ   rà   )r   rA   r   r   r   ræ   Ü  s    
z_UnixWritePipeTransport._closec             C   s4   z| j  |¡ W d | j ¡  d | _d | _ d | _X d S )N)r¿   rî   r½   r    r¼   )r   rA   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   rV   $  s"   %	!	

rV   c               @   s   e Zd Zdd„ ZdS )rZ   c       	   	   K   sf   d }|t jkrt ¡ \}}t j|f||||d|dœ|—Ž| _|d k	rb| ¡  t| ¡ d|d| j_	d S )NF)r`   ra   rb   rc   Úuniversal_newlinesrd   Úwb)Ú	buffering)
Ú
subprocessÚPIPErt   Ú
socketpairÚPopenÚ_procr    rÏ   Údetachra   )	r   r@   r`   ra   rb   rc   rd   re   Zstdin_wr   r   r   Ú_startð  s    
z_UnixSubprocessTransport._startN)r¶   r·   r¸   r  r   r   r   r   rZ   î  s   rZ   c               @   s@   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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   rk   r?   r@   r   r   r   r[     s    	z&AbstractChildWatcher.add_child_handlerc             C   s
   t ƒ ‚dS )z Removes the handler for process 'pid'.

        The function returns True if the handler was successfully removed,
        False if there was nothing to remove.N)r  )r   rk   r   r   r   Úremove_child_handler#  s    z)AbstractChildWatcher.remove_child_handlerc             C   s
   t ƒ ‚dS )zÔAttach 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.
        N)r  )r   r„   r   r   r   Úattach_loop+  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.
        N)r  )r   r   r   r   r    5  s    zAbstractChildWatcher.closec             C   s
   t ƒ ‚dS )zdEnter the watcher's context and allow starting new processes

        This function must return selfN)r  )r   r   r   r   Ú	__enter__<  s    zAbstractChildWatcher.__enter__c             C   s
   t ƒ ‚dS )zExit the watcher's contextN)r  )r   ÚaÚbÚcr   r   r   Ú__exit__B  s    zAbstractChildWatcher.__exit__N)
r¶   r·   r¸   r¹   r[   r  r  r    r  r  r   r   r   r   r     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 )N)r¼   Ú
_callbacks)r   r   r   r   r   I  s    zBaseChildWatcher.__init__c             C   s   |   d ¡ d S )N)r  )r   r   r   r   r    M  s    zBaseChildWatcher.closec             C   s
   t ƒ ‚d S )N)r  )r   Úexpected_pidr   r   r   Ú_do_waitpidP  s    zBaseChildWatcher._do_waitpidc             C   s
   t ƒ ‚d S )N)r  )r   r   r   r   Ú_do_waitpid_allS  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)rM   r   ÚAbstractEventLooprq   r¼   r  r%   r&   ÚRuntimeWarningr$   r3   ÚSIGCHLDrC   Ú	_sig_chldr  )r   r„   r   r   r   r  V  s    
zBaseChildWatcher.attach_loopc          
   C   sF   y|   ¡  W n4 tk
r@ } z| j d|dœ¡ W d d }~X Y nX d S )Nz$Unknown exception in SIGCHLD handler)rê   rë   )r  r^   r¼   rí   )r   rA   r   r   r   r#  j  s    zBaseChildWatcher._sig_chldc             C   s2   t  |¡rt  |¡ S t  |¡r*t  |¡S |S d S )N)rr   ÚWIFSIGNALEDÚWTERMSIGÚ	WIFEXITEDÚWEXITSTATUS)r   Ústatusr   r   r   Ú_compute_returncodev  s
    


z$BaseChildWatcher._compute_returncodeN)
r¶   r·   r¸   r   r    r  r  r  r#  r)  r   r   r   r   r  G  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 )N)r  r(   r   r    )r   )r   r   r   r      s    
zSafeChildWatcher.closec             C   s   | S )Nr   )r   r   r   r   r  “  s    zSafeChildWatcher.__enter__c             C   s   d S )Nr   )r   r  r  r  r   r   r   r  –  s    zSafeChildWatcher.__exit__c             G   s.   | j d krtdƒ‚||f| j|< |  |¡ d S )NzICannot add child handler, the child watcher does not have a loop attached)r¼   r8   r  r  )r   rk   r?   r@   r   r   r   r[   ™  s
    
z"SafeChildWatcher.add_child_handlerc             C   s&   y| j |= dS  tk
r    dS X d S )NTF)r  rG   )r   rk   r   r   r   r  ¤  s
    z%SafeChildWatcher.remove_child_handlerc             C   s"   xt | jƒD ]}|  |¡ qW d S )N)r#   r  r  )r   rk   r   r   r   r  «  s    z SafeChildWatcher._do_waitpid_allc             C   sÒ   |dkst ‚yt |tj¡\}}W n( tk
rJ   |}d}t d|¡ Y n0X |dkrXd S |  |¡}| j 	¡ rzt 
d||¡ y| j |¡\}}W n. tk
r¼   | j 	¡ r¸tjd|dd Y nX |||f|žŽ  d S )Nr   éÿ   z8Unknown child process pid %d, will report returncode 255z$process %s exited with returncode %sz'Child watcher got an unexpected pid: %rT)ré   )rq   rr   ÚwaitpidÚWNOHANGÚChildProcessErrorr   rý   r)  r¼   rÝ   rì   r  ÚpoprG   )r   r  rk   r(  rl   r?   r@   r   r   r   r  °  s,    


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 )Nr   )r   r   Ú	threadingÚLockÚ_lockÚ_zombiesÚ_forks)r   )r   r   r   r   Ý  s    

zFastChildWatcher.__init__c                s"   | j  ¡  | j ¡  tƒ  ¡  d S )N)r  r(   r2  r   r    )r   )r   r   r   r    ã  s    

zFastChildWatcher.closec          	   C   s$   | j  |  jd7  _| S Q R X d S )Nr   )r1  r3  )r   r   r   r   r  è  s    zFastChildWatcher.__enter__c          	   C   sT   | j 8 |  jd8  _| js"| js&d S t| jƒ}| j ¡  W d Q R X t d|¡ d S )Nr   z5Caught subprocesses termination from unknown pids: %s)r1  r3  r2  r9   r(   r   rý   )r   r  r  r  Zcollateral_victimsr   r   r   r  î  s    
zFastChildWatcher.__exit__c          	   G   sz   | j stdƒ‚| jd kr tdƒ‚| j: y| j |¡}W n" tk
rZ   ||f| j|< d S X W d Q R X |||f|žŽ  d S )NzMust use the context managerzICannot add child handler, the child watcher does not have a loop attached)	r3  rq   r¼   r8   r1  r2  r.  rG   r  )r   rk   r?   r@   rl   r   r   r   r[   ü  s    
z"FastChildWatcher.add_child_handlerc             C   s&   y| j |= dS  tk
r    dS X d S )NTF)r  rG   )r   rk   r   r   r   r    s
    z%FastChildWatcher.remove_child_handlerc          	   C   sö   xðyt  dt j¡\}}W n tk
r,   d S X |dkr:d S |  |¡}| jv y| j |¡\}}W nB tk
r¢   | j	rš|| j
|< | j ¡ r˜t d||¡ wd }Y nX | j ¡ r¼t d||¡ W d Q R X |d krÞt d||¡ q|||f|žŽ  qW d S )Nr-   r   z,unknown process %s exited with returncode %sz$process %s exited with returncode %sz8Caught subprocess termination from unknown pid: %d -> %d)rr   r+  r,  r-  r)  r1  r  r.  rG   r3  r2  r¼   rÝ   r   rì   rý   )r   rk   r(  rl   r?   r@   r   r   r   r    s6    





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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 )N)r   r   Ú_watcher)r   )r   r   r   r   E  s    
z$_UnixDefaultEventLoopPolicy.__init__c          	   C   sH   t j8 | jd kr:tƒ | _tt ¡ tjƒr:| j | j	j
¡ W d Q R X d S )N)r   r1  r5  r   rM   r/  Úcurrent_threadÚ_MainThreadr  Ú_localr¼   )r   r   r   r   Ú_init_watcherI  s    
z)_UnixDefaultEventLoopPolicy._init_watcherc                s6   t ƒ  |¡ | jdk	r2tt ¡ tjƒr2| j |¡ dS )zÑSet 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_loopr5  rM   r/  r6  r7  r  )r   r„   )r   r   r   r:  Q  s    
z*_UnixDefaultEventLoopPolicy.set_event_loopc             C   s   | j dkr|  ¡  | j S )zzGet the watcher for child processes.

        If not yet set, a SafeChildWatcher object is automatically created.
        N)r5  r9  )r   r   r   r   rX   _  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)rM   r   rq   r5  r    )r   rf   r   r   r   Úset_child_watcheri  s    

z-_UnixDefaultEventLoopPolicy.set_child_watcher)r¶   r·   r¸   r¹   r   Ú_loop_factoryr   r9  r:  rX   r;  rº   r   r   )r   r   r4  A  s   
r4  )-r¹   r=   r—   rr   rÔ   r3   rt   r†   r  r!   r/  r%   Ú r   r   r   r   r   r   r	   r
   r   Úlogr   Ú__all__ró   ÚImportErrorr   ZBaseSelectorEventLoopr   ÚReadTransportrP   Ú_FlowControlMixinÚWriteTransportrV   ZBaseSubprocessTransportrZ   r   r  r   r   ÚBaseDefaultEventLoopPolicyr4  r   r   r   r   r   r   Ú<module>   sP   
  |~ JF=On3