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

    Adds signal handling and UNIX Domain Socket support to SelectorEventLoop.
    Nc                s   t    j |  i  |  _ d  S)N)super__init___signal_handlers)selfselector)	__class__r   r   r   0   s    z_UnixSelectorEventLoop.__init__c             C   s
   t  j   S)N)socketZ
socketpair)r   r   r   r   _socketpair4   s    z"_UnixSelectorEventLoop._socketpairc                s8   t    j   x$ t |  j  D] } |  j |  q Wd  S)N)r   closelistr   remove_signal_handler)r   sig)r   r   r   r"   7   s    z_UnixSelectorEventLoop.closec             C   s+   x$ | D] } | s q |  j  |  q Wd  S)N)_handle_signal)r   datar   r   r   r   _process_self_data<   s    z)_UnixSelectorEventLoop._process_self_datac          +   G   s  t  j |  s t  j |  r* t d   |  j |  |  j   y t j |  j j	    Wn= t
 t f k
 r } z t t |    WYd d } ~ Xn Xt j | | |   } | |  j | <y$ t j | t  t j | d  Wn t k
 r} z |  j | =|  j sXy t j d  Wn; t
 t f k
 rW} z t j d |  WYd d } ~ Xn X| j t j k rt d j |    n   WYd d } ~ Xn Xd 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()NFr   zset_wakeup_fd(-1) failed: %sz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format)r   r%   callbackargsexchandleZnexcr   r   r   add_signal_handlerC   s0    
%
	#z)_UnixSelectorEventLoop.add_signal_handlerc             C   sL   |  j  j |  } | d k r" d S| j r; |  j |  n |  j |  d S)z2Internal helper that is the actual signal handler.N)r   getZ
_cancelledr$   Z_add_callback_signalsafe)r   r%   r;   r   r   r   r&   p   s    	z%_UnixSelectorEventLoop._handle_signalc          &   C   s  |  j  |  y |  j | =Wn t k
 r3 d SYn X| t j k rO t j } n	 t j } y t j | |  WnR t k
 r } z2 | j t j	 k r t
 d j |    n   WYd d } ~ Xn X|  j sy t j d  Wn; t t f k
 r} z t j d |  WYd d } ~ Xn Xd S)zwRemove a handler for a signal.  UNIX only.

        Return True if a signal handler was removed, False if not.
        Fzsig {} cannot be caughtNr   zset_wakeup_fd(-1) failed: %sTr)   )r+   r   KeyErrorr,   SIGINTdefault_int_handlerSIG_DFLr0   r5   r6   r1   r7   r-   r/   r   r4   )r   r%   Zhandlerr:   r   r   r   r$   z   s(    			#z,_UnixSelectorEventLoop.remove_signal_handlerc             C   sb   t  | t  s$ t d j |    d | k o> t j k  n s^ t d j | t j    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 {!r}r   zsig {} out of range(1, {})N)
isinstanceintr*   r7   r,   NSIGr/   )r   r%   r   r   r   r+      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   rF   rG   rH   rI   r   r   r   _make_write_pipe_transport   s    z1_UnixSelectorEventLoop._make_write_pipe_transportc	             k   s   t  j    }
 |  j   } t |  | | | | | | | d | d | |	 } |
 j | j   |  j |  y | Ed  HWn+ t k
 r } z | } WYd  d  } ~ Xn Xd  } | d  k	 r | j   | j	   Ed  H|  Wd  QRX| S)NrH   rI   )
r   get_child_watcherZcreate_future_UnixSubprocessTransportadd_child_handlerZget_pid_child_watcher_callback	Exceptionr"   Z_wait)r   rG   r9   shellstdinstdoutstderrbufsizerI   kwargswatcherrH   transpr:   errr   r   r   _make_subprocess_transport   s$    		
z1_UnixSelectorEventLoop._make_subprocess_transportc             C   s   |  j  | j |  d  S)N)Zcall_soon_threadsafeZ_process_exited)r   pid
returncoderY   r   r   r   rP      s    z._UnixSelectorEventLoop._child_watcher_callbacksslsockserver_hostnamec            c   s,  | d  k s! t  | t  s! t  | rB | d  k rZ t d   n | d  k	 rZ t d   | d  k	 r | d  k	 r~ t d   t j t j t j d  } y& | j d  |  j | |  Ed  HWq | j	     Yq Xn% | d  k r t d   | j d  |  j
 | | | |  Ed  H\ } } | | f S)Nz/you have to pass server_hostname when using sslz+server_hostname is only meaningful with sslz3path and sock can not be specified at the same timer   Fzno path and sock were specified)rB   r2   AssertionErrorr/   r    AF_UNIXSOCK_STREAMsetblockingZsock_connectr"   Z_create_connection_transport)r   protocol_factorypathr^   r_   r`   	transportrG   r   r   r   create_unix_connection   s0    !	
z-_UnixSelectorEventLoop.create_unix_connectionbacklogd   c      	      C   su  t  | t  r t d   | d  k	 r | d  k	 r? t d   t j t j t j  } y | j |  Wq,t k
 r } zK | j	   | j
 t
 j k r d j |  } t t
 j |  d   n   WYd  d  } ~ Xq,| j	     Yq,Xn? | d  k rt d   | j t j k r,t d j |    t j |  | g  } | j |  | j d  |  j | | | |  | S)Nz*ssl argument must be an SSLContext or Nonez3path and sock can not be specified at the same timezAddress {!r} is already in usez-path was not specified, and no sock specifiedz+A UNIX Domain Socket was expected, got {!r}F)rB   boolr*   r/   r    rb   rc   Zbindr0   r"   r5   Z
EADDRINUSEr7   Zfamilyr   ZServerZlistenrd   Z_start_serving)	r   re   rf   r_   ri   r^   r:   msgZserverr   r   r   create_unix_server   s:    	

	z)_UnixSelectorEventLoop.create_unix_server)__name__
__module____qualname____doc__r   r!   r"   r(   r<   r&   r$   r+   rJ   rL   r   r[   rP   rh   rm   r   r   )r   r   r   *   s,   -
  r   set_blockingc             C   s   t  j |  d  d  S)NF)osrr   )fdr   r   r   _set_nonblocking  s    ru   c             C   s<   t  j  |  t  j  } | t j B} t  j  |  t  j |  d  S)N)fcntlZF_GETFLrs   
O_NONBLOCKZF_SETFL)rt   flagsr   r   r   ru   $  s    c                   s   e  Z d  Z d Z d d   f d d  Z d d   Z d d	   Z d
 d   Z d d   Z d d   Z	 d d   Z
 e j r d d   Z d d d  Z d d   Z d d   Z   S)rE      i   Nc                s  t    j |  | |  j d <| |  _ | |  _ | j   |  _ t j |  j  j	 } t
 j |  p} t
 j |  p} t
 j |  s t d   t |  j  | |  _ d |  _ |  j j |  j j |   |  j j |  j j |  j |  j  | d  k	 r|  j j t j | d   d  S)NrF   z)Pipe transport is for pipes/sockets only.F)r   r   _extra_loop_piper.   _filenors   fstatst_modestatS_ISFIFOS_ISSOCKS_ISCHRr/   ru   	_protocol_closing	call_soonconnection_made
add_reader_read_readyr	   _set_result_unless_cancelled)r   looprF   rG   rH   rI   mode)r   r   r   r   .  s&    				z_UnixReadPipeTransport.__init__c             C   s  |  j  j g } |  j d  k r. | j d  n |  j rD | j d  | j d |  j  t |  j d d   } |  j d  k	 r | d  k	 r t j	 | |  j t
 j  } | r | j d  q | j d  n, |  j d  k	 r | j d  n | j d  d d	 j |  S)
Nclosedclosingzfd=%s	_selectorpollingidleopenz<%s> )r   rn   r|   appendr   r}   getattrr{   r
   _test_selector_eventr   Z
EVENT_READjoin)r   r4   r   r   r   r   r   __repr__E  s$    	z_UnixReadPipeTransport.__repr__c             C   s   y t  j |  j |  j  } WnL t t f k
 r6 Yn t k
 rj } z |  j | d  WYd  d  } ~ Xn X| r |  j j	 |  ng |  j
 j   r t j d |   d |  _ |  j
 j |  j  |  j
 j |  j j  |  j
 j |  j d   d  S)Nz"Fatal read error on pipe transportz%r was closed by peerT)rs   readr}   max_sizeBlockingIOErrorInterruptedErrorr0   _fatal_errorr   Zdata_receivedr{   	get_debugr   r4   r   remove_readerr   Zeof_received_call_connection_lost)r   r'   r:   r   r   r   r   [  s    #	z"_UnixReadPipeTransport._read_readyc             C   s   |  j  j |  j  d  S)N)r{   r   r}   )r   r   r   r   pause_readingm  s    z$_UnixReadPipeTransport.pause_readingc             C   s   |  j  j |  j |  j  d  S)N)r{   r   r}   r   )r   r   r   r   resume_readingp  s    z%_UnixReadPipeTransport.resume_readingc             C   s   |  j  S)N)r   )r   r   r   r   
is_closings  s    z!_UnixReadPipeTransport.is_closingc             C   s   |  j  s |  j d   d  S)N)r   _close)r   r   r   r   r"   v  s    	z_UnixReadPipeTransport.closec             C   s4   |  j  d  k	 r0 t j d |  t  |  j  j   d  S)Nzunclosed transport %r)r|   warningswarnResourceWarningr"   )r   r   r   r   __del__~  s    z_UnixReadPipeTransport.__del__zFatal error on pipe transportc          	   C   s   t  | t  rL | j t j k rL |  j j   rw t j d |  | d d n+ |  j j d | d | d |  d |  j	 i  |  j
 |  d  S)Nz%r: %sexc_infoTmessage	exceptionrg   rG   )rB   r0   r5   ZEIOr{   r   r   debugcall_exception_handlerr   r   )r   r:   r   r   r   r   r     s    !	z#_UnixReadPipeTransport._fatal_errorc             C   s6   d |  _  |  j j |  j  |  j j |  j |  d  S)NT)r   r{   r   r}   r   r   )r   r:   r   r   r   r     s    	z_UnixReadPipeTransport._closec             C   sD   z |  j  j |  Wd  |  j j   d  |  _ d  |  _  d  |  _ Xd  S)N)r   connection_lostr|   r"   r{   )r   r:   r   r   r   r     s    		z,_UnixReadPipeTransport._call_connection_losti   )rn   ro   rp   r   r   r   r   r   r   r   r"   r   PY34r   r   r   r   r   r   )r   r   rE   *  s   	rE   c                   s   e  Z d  Z d 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 e j r d d   Z d d   Z d d d  Z d d d  Z d d    Z   S)!rK   Nc                s:  t    j | |  | |  j d <| |  _ | j   |  _ t j |  j  j } t	 j
 |  } | p} t	 j |  p} t	 j |  s t d   t |  j  | |  _ g  |  _ d |  _ d |  _ |  j j |  j j |   | s t j j d  r|  j j |  j j |  j |  j  | d  k	 r6|  j j t j | d   d  S)NrF   z?Pipe transport is only for pipes, sockets and character devicesr   FZaix)r   r   rz   r|   r.   r}   rs   r~   r   r   r   r   r   r/   ru   r   _buffer
_conn_lostr   r{   r   r   sysplatform
startswithr   r   r	   r   )r   r   rF   rG   rH   rI   r   Z	is_socket)r   r   r   r     s,    					z _UnixWritePipeTransport.__init__c             C   s#  |  j  j g } |  j d  k r. | j d  n |  j rD | j d  | j d |  j  t |  j d d   } |  j d  k	 r | d  k	 r t j	 | |  j t
 j  } | r | j d  n | j d  |  j   } | j d |  n, |  j d  k	 r| j d  n | j d  d	 d
 j |  S)Nr   r   zfd=%sr   r   r   z
bufsize=%sr   z<%s>r   )r   rn   r|   r   r   r}   r   r{   r
   r   r   ZEVENT_WRITEget_write_buffer_sizer   )r   r4   r   r   rV   r   r   r   r     s(    	z _UnixWritePipeTransport.__repr__c             C   s   t  d d   |  j D  S)Nc             s   s   |  ] } t  |  Vq d  S)N)len).0r'   r   r   r   	<genexpr>  s    z@_UnixWritePipeTransport.get_write_buffer_size.<locals>.<genexpr>)sumr   )r   r   r   r   r     s    z-_UnixWritePipeTransport.get_write_buffer_sizec             C   sI   |  j  j   r t j d |   |  j r; |  j t    n
 |  j   d  S)Nz%r was closed by peer)r{   r   r   r4   r   r   BrokenPipeError)r   r   r   r   r     s
    	z#_UnixWritePipeTransport._read_readyc             C   s  t  | t t t f  s* t t |    t  | t  rE t |  } | sO d  S|  j sa |  j r |  j t j	 k r t
 j d  |  j d 7_ d  S|  j shy t j |  j |  } Wne t t f k
 r d } YnH t k
 r} z( |  j d 7_ |  j | d  d  SWYd  d  } ~ Xn X| t |  k r3d  S| d k rO| | d   } |  j j |  j |  j  |  j j |  |  j   d  S)Nz=pipe closed by peer or os.write(pipe, data) raised exception.r   r   z#Fatal write error on pipe transport)rB   bytes	bytearray
memoryviewra   reprr   r   r   Z!LOG_THRESHOLD_FOR_CONNLOST_WRITESr   warningr   rs   writer}   r   r   rQ   r   r   r{   Z
add_writer_write_readyr   Z_maybe_pause_protocol)r   r'   nr:   r   r   r   r     s4    *	
z_UnixWritePipeTransport.writec             C   sa  d j  |  j  } | s$ t d   |  j j   y t j |  j |  } Wn~ t t f k
 rt |  j j	 |  Yn t
 k
 r } z7 |  j d 7_ |  j j |  j  |  j | d  WYd  d  } ~ Xn X| t |  k r1|  j j |  j  |  j   |  j r-|  j r-|  j j |  j  |  j d   d  S| d k rM| | d   } |  j j	 |  d  S)N    zData should not be emptyr   z#Fatal write error on pipe transportr   )r   r   ra   clearrs   r   r}   r   r   r   rQ   r   r{   remove_writerr   r   Z_maybe_resume_protocolr   r   r   )r   r'   r   r:   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   s[   |  j  r d  S|  j s t  d |  _  |  j sW |  j j |  j  |  j j |  j d   d  S)NT)	r   r|   ra   r   r{   r   r}   r   r   )r   r   r   r   	write_eof)  s    			z!_UnixWritePipeTransport.write_eofc             C   s   |  j  S)N)r   )r   r   r   r   r   2  s    z"_UnixWritePipeTransport.is_closingc             C   s'   |  j  d  k	 r# |  j r# |  j   d  S)N)r|   r   r   )r   r   r   r   r"   5  s    z_UnixWritePipeTransport.closec             C   s4   |  j  d  k	 r0 t j d |  t  |  j  j   d  S)Nzunclosed transport %r)r|   r   r   r   r"   )r   r   r   r   r   >  s    z_UnixWritePipeTransport.__del__c             C   s   |  j  d   d  S)N)r   )r   r   r   r   abortC  s    z_UnixWritePipeTransport.abortzFatal error on pipe transportc          	   C   sy   t  | t j  r= |  j j   rh t j d |  | d d n+ |  j j d | d | d |  d |  j i  |  j	 |  d  S)Nz%r: %sr   Tr   r   rg   rG   )
rB   r   Z_FATAL_ERROR_IGNOREr{   r   r   r   r   r   r   )r   r:   r   r   r   r   r   F  s    	z$_UnixWritePipeTransport._fatal_errorc             C   s_   d |  _  |  j r% |  j j |  j  |  j j   |  j j |  j  |  j j |  j |  d  S)NT)	r   r   r{   r   r}   r   r   r   r   )r   r:   r   r   r   r   T  s    		z_UnixWritePipeTransport._closec             C   sD   z |  j  j |  Wd  |  j j   d  |  _ d  |  _  d  |  _ Xd  S)N)r   r   r|   r"   r{   )r   r:   r   r   r   r   \  s    		z-_UnixWritePipeTransport._call_connection_lost)rn   ro   rp   r   r   r   r   r   r   r   r   r   r"   r   r   r   r   r   r   r   r   r   )r   r   rK     s    !	!		rK   set_inheritablec             C   si   t  t d d  } t j |  t j  } | sJ t j |  t j | | B n t j |  t j | | @ d  S)NZ
FD_CLOEXECr   )r   rv   ZF_GETFDZF_SETFD)rt   ZinheritableZcloexec_flagoldr   r   r   _set_inheritablel  s
    r   c               @   s   e  Z d  Z d d   Z d S)rN   c       	      K   s   d  } | t  j k r= |  j j   \ } } t | j   d  t  j | d | d | d | d | d d d | | |  _ | d  k	 r | j   t	 | j
   d d	 | |  j _ d  S)
NFrR   rS   rT   rU   Zuniversal_newlinesrV   wb	buffering)
subprocessPIPEr{   r!   r   r.   Popen_procr"   r   detachrS   )	r   r9   rR   rS   rT   rU   rV   rW   Zstdin_wr   r   r   _startx  s    
z_UnixSubprocessTransport._startN)rn   ro   rp   r   r   r   r   r   rN   v  s   rN   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   r\   r8   r9   r   r   r   rO     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.N)r   )r   r\   r   r   r   remove_child_handler  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.
        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"     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__  s    zAbstractChildWatcher.__exit__N)
rn   ro   rp   rq   rO   r   r   r"   r   r   r   r   r   r   r     s   
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  |  _  d  S)N)r{   )r   r   r   r   r     s    zBaseChildWatcher.__init__c             C   s   |  j  d   d  S)N)r   )r   r   r   r   r"     s    zBaseChildWatcher.closec             C   s   t     d  S)N)r   )r   expected_pidr   r   r   _do_waitpid  s    zBaseChildWatcher._do_waitpidc             C   s   t     d  S)N)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	 rF |  j j t j  | |  _ | d  k	 r{ | j t j |  j	  |  j
   d  S)N)rB   r   ZAbstractEventLoopra   r{   r$   r,   SIGCHLDr<   	_sig_chldr   )r   r   r   r   r   r     s    $	zBaseChildWatcher.attach_loopc             C   sV   y |  j    WnA t k
 rQ } z! |  j j d d d | i  WYd  d  } ~ Xn Xd  S)Nr   z$Unknown exception in SIGCHLD handlerr   )r   rQ   r{   r   )r   r:   r   r   r   r     s    	zBaseChildWatcher._sig_chldc             C   sA   t  j |  r t  j |  St  j |  r9 t  j |  S| Sd  S)N)rs   WIFSIGNALEDWTERMSIG	WIFEXITEDWEXITSTATUS)r   statusr   r   r   _compute_returncode  s
    z$BaseChildWatcher._compute_returncodeN)
rn   ro   rp   r   r"   r   r   r   r   r   r   r   r   r   r     s   r   c                   s   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
 d d   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   t    j   i  |  _ d  S)N)r   r   
_callbacks)r   )r   r   r   r     s    zSafeChildWatcher.__init__c                s   |  j  j   t   j   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$   | | f |  j  | <|  j |  d  S)N)r   r   )r   r\   r8   r9   r   r   r   rO   $  s    z"SafeChildWatcher.add_child_handlerc             C   s/   y |  j  | =d SWn t k
 r* d SYn Xd  S)NTF)r   r>   )r   r\   r   r   r   r   *  s
    
z%SafeChildWatcher.remove_child_handlerc             C   s+   x$ t  |  j  D] } |  j |  q Wd  S)N)r#   r   r   )r   r\   r   r   r   r   1  s    z SafeChildWatcher._do_waitpid_allc             C   s  | d k s t   y t j | t j  \ } } Wn. t k
 ra | } d } t j d |  YnB X| d k rr d  S|  j |  } |  j j	   r t j
 d | |  y |  j j |  \ } } Wn7 t k
 r |  j j	   r t j d | d d Yn X| | | |  d  S)Nr      z8Unknown child process pid %d, will report returncode 255z$process %s exited with returncode %sz'Child watcher got an unexpected pid: %rr   T)ra   rs   waitpidWNOHANGChildProcessErrorr   r   r   r{   r   r   r   popr>   )r   r   r\   r   r]   r8   r9   r   r   r   r   6  s,    	
	zSafeChildWatcher._do_waitpid)rn   ro   rp   rq   r   r"   r   r   rO   r   r   r   r   r   )r   r   r     s   	c                   sv   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
   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    j   i  |  _ t j   |  _ i  |  _ d |  _ d  S)Nr   )r   r   r   	threadingZLock_lock_zombies_forks)r   )r   r   r   r   c  s
    		zFastChildWatcher.__init__c                s+   |  j  j   |  j j   t   j   d  S)N)r   r   r   r   r"   )r   )r   r   r   r"   j  s    zFastChildWatcher.closec          
   C   s(   |  j   |  j d 7_ |  SWd  QRXd  S)Nr   )r   r   )r   r   r   r   r   o  s    
zFastChildWatcher.__enter__c          
   C   sg   |  j  G |  j d 8_ |  j s, |  j r0 d  St |  j  } |  j j   Wd  QRXt j d |  d  S)Nr   z5Caught subprocesses termination from unknown pids: %s)r   r   r   r2   r   r   r   )r   r   r   r   Zcollateral_victimsr   r   r   r   u  s    
zFastChildWatcher.__exit__c             G   s|   |  j  s t d   |  j G y |  j j |  } Wn) t k
 r` | | f |  j | <d  SYn XWd  QRX| | | |  d  S)NzMust use the context manager)r   ra   r   r   r   r>   r   )r   r\   r8   r9   r]   r   r   r   rO     s    
z"FastChildWatcher.add_child_handlerc             C   s/   y |  j  | =d SWn t k
 r* d SYn Xd  S)NTF)r   r>   )r   r\   r   r   r   r     s
    
z%FastChildWatcher.remove_child_handlerc             C   s9  x2y t  j d t  j  \ } } Wn t k
 r: d  SYn  X| d k rK d  S|  j |  } |  j  y |  j j |  \ } } WnS t k
 r |  j	 r | |  j
 | <|  j j   r t j d | |  w d  } Yn# X|  j j   r t j d | |  Wd  QRX| d  k r!t j d | |  q | | | |  q Wd  S)Nr   r   z,unknown process %s exited with returncode %sz$process %s exited with returncode %sz8Caught subprocess termination from unknown pid: %d -> %dr)   )rs   r   r   r   r   r   r   r   r>   r   r   r{   r   r   r   r   )r   r\   r   r]   r8   r9   r   r   r   r     s6    	
		
	z FastChildWatcher._do_waitpid_all)rn   ro   rp   rq   r   r"   r   r   rO   r   r   r   r   )r   r   r   Y  s   	c                   sd   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
   S)_UnixDefaultEventLoopPolicyz:UNIX event loop policy with a watcher for child processes.c                s   t    j   d  |  _ d  S)N)r   r   _watcher)r   )r   r   r   r     s    z$_UnixDefaultEventLoopPolicy.__init__c          
   C   s^   t  j N |  j d  k rS t   |  _ t t j   t j  rS |  j j |  j	 j
  Wd  QRXd  S)N)r   r   r   r   rB   r   current_thread_MainThreadr   _localr{   )r   r   r   r   _init_watcher  s    
z)_UnixDefaultEventLoopPolicy._init_watcherc                sK   t    j |  |  j d k	 rG t t j   t j  rG |  j 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_loopr   rB   r   r   r   r   )r   r   )r   r   r   r     s    z*_UnixDefaultEventLoopPolicy.set_event_loopc             C   s    |  j  d k r |  j   |  j  S)zzGet the watcher for child processes.

        If not yet set, a SafeChildWatcher object is automatically created.
        N)r   r   )r   r   r   r   rM     s    
z-_UnixDefaultEventLoopPolicy.get_child_watcherc             C   sJ   | d k s! t  | t  s! t  |  j d k	 r= |  j j   | |  _ d S)z$Set the watcher for child processes.N)rB   r   ra   r   r"   )r   rX   r   r   r   set_child_watcher  s    !z-_UnixDefaultEventLoopPolicy.set_child_watcher)rn   ro   rp   rq   r   Z_loop_factoryr   r   r   rM   r   r   r   )r   r   r     s   
r   )2rq   r5   rs   r,   r    r   r   r   r   r    r   r   r   r   r   r   r	   r
   r   r   r   logr   __all__r   ImportErrorr   ZBaseSelectorEventLoopr   hasattrru   rv   ZReadTransportrE   Z_FlowControlMixinZWriteTransportrK   r   r   ZBaseSubprocessTransportrN   r   r   r   r   ZBaseDefaultEventLoopPolicyr   r   r   r   r   r   r   <module>   s^   v
F6Ni2