
\[\z                 @   sS  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	 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 r)e d   n  d d   Z Gd d   d e j  Z e e d  rl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" 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 Z+ e* Z, d S))z2Selector event loop for Unix with signal handling.    N   )base_events)base_subprocess)	constants)events)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 )signumZframer   r   )/usr/lib/python3.4/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)selfZselector)	__class__r   r   r   ,   s    z_UnixSelectorEventLoop.__init__c             C   s
   t  j   S)N)socketZ
socketpair)r   r   r   r   _socketpair0   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   3   s    z_UnixSelectorEventLoop.closec             C   s.   x' | D] } | s q n  |  j  |  q Wd  S)N)_handle_signal)r   datar   r   r   r   _process_self_data8   s    z)_UnixSelectorEventLoop._process_self_datac          +   G   sk  |  j  |  y t j |  j j    Wn= t t f k
 rf } z t t |    WYd d } ~ Xn Xt	 j
 | | |   } | |  j | <y$ t j | t  t j | d  Wn t k
 rf} z |  j | =|  j s'y t j d  Wq't t f k
 r#} z t j d |  WYd d } ~ Xq'Xn  | j t j k rQ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.
        NFr   zset_wakeup_fd(-1) failed: %szsig {} cannot be caught)_check_signal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_handler?   s(    %
	&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    r5   r   r   r   r!   g   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  Wqt t f k
 r} z t j d |  WYd d } ~ XqXn  d 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_DFLr*   r/   r0   r+   r1   r'   r)   r   r.   )r   r    Zhandlerr4   r   r   r   r   q   s(    			&z,_UnixSelectorEventLoop.remove_signal_handlerc             C   sh   t  | t  s' t d j |    n  d | k oA t j k  n sd t d j | t j    n  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int	TypeErrorr1   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   rA   rB   rC   rD   r   r   r   _make_write_pipe_transport   s    z1_UnixSelectorEventLoop._make_write_pipe_transportc	             k   sn   t  j   \ }
 t |  | | | | | | | d | |	 } | j   Dd  H|
 j | j   |  j |  Wd  QX| S)NrD   )r   get_child_watcher_UnixSubprocessTransportZ
_post_initadd_child_handlerZget_pid_child_watcher_callback)r   rB   r3   shellstdinstdoutstderrbufsizerD   kwargswatchertranspr   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
returncoderS   r   r   r   rK      s    z._UnixSelectorEventLoop._child_watcher_callbacksslsockserver_hostnamec            c   s8  | d  k s! t  | t  s! t  | rE | d  k r` t d   q` n | d  k	 r` t d   n  | d  k	 r | d  k	 r t d   n  t j t j t j d  } y& | j d  |  j | |  Dd  HWq| j	     YqXn( | d  k r t d   n  | j d  |  j
 | | | |  Dd  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)r<   r,   AssertionErrorr)   r   AF_UNIXSOCK_STREAMsetblockingZsock_connectr   Z_create_connection_transport)r   protocol_factorypathrW   rX   rY   	transportrB   r   r   r   create_unix_connection   s0    !
z-_UnixSelectorEventLoop.create_unix_connectionbacklogd   c      	      C   s  t  | t  r t d   n  | d  k	 r | d  k	 rE t d   n  t j t j t j  } y | j |  Wq8t k
 r } zK | j	   | j
 t
 j k r d j |  } t t
 j |  d   n   WYd  d  } ~ Xq8| j	     Yq8XnE | d  k rt d   n  | j t j k r8t d j |    n  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)r<   boolr>   r)   r   r[   r\   Zbindr*   r   r/   Z
EADDRINUSEr1   Zfamilyr   ZServerZlistenr]   Z_start_serving)	r   r^   r_   rX   rb   rW   r4   msgZserverr   r   r   create_unix_server   s:    

z)_UnixSelectorEventLoop.create_unix_server)__name__
__module____qualname____doc__r   r   r   r#   r6   r!   r   r%   rE   rG   r
   rT   rK   ra   rf   r   r   )r   r   r   &   s,   (
  r   set_blockingc             C   s   t  j |  d  d  S)NF)osrk   )fdr   r   r   _set_nonblocking  s    rn   c             C   s<   t  j  |  t  j  } | t j B} t  j  |  t  j |  d  S)N)fcntlZF_GETFLrl   
O_NONBLOCKZF_SETFL)rm   flagsr   r   r   rn     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 d  Z
 d d   Z d d   Z   S)r@      i   Nc                s	  t    j |  | |  j d <| |  _ | |  _ | j   |  _ t j |  j  j	 } t
 j |  p} t
 j |  p} t
 j |  s t d   n  t |  j  | |  _ d |  _ |  j j |  j |  j  |  j j |  j j |   | d  k	 r|  j j | j d   n  d  S)NrA   z)Pipe transport is for pipes/sockets only.F)r   r   _extra_loop_piper(   _filenorl   fstatst_modestatS_ISFIFOS_ISSOCKS_ISCHRr)   rn   	_protocol_closing
add_reader_read_ready	call_soonconnection_made_set_result_unless_cancelled)r   looprA   rB   rC   rD   mode)r   r   r   r     s"    				z_UnixReadPipeTransport.__init__c             C   s   |  j  j d |  j g } |  j d  k	 ro t j |  j j |  j t j	  } | r_ | j
 d  q| | j
 d  n | j
 d  d d j |  S)Nzfd=%spollingidleclosedz<%s> )r   rg   rv   ru   r   _test_selector_eventrt   	_selectorr   Z
EVENT_READappendjoin)r   r.   r   r   r   r   __repr__)  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	 |  nj |  j
 j   r t j d |   n  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)rl   readrv   max_sizeBlockingIOErrorInterruptedErrorr*   _fatal_errorr}   Zdata_receivedrt   	get_debugr   r.   r~   remove_readerr   Zeof_received_call_connection_lost)r   r"   r4   r   r   r   r   7  s    #	z"_UnixReadPipeTransport._read_readyc             C   s   |  j  j |  j  d  S)N)rt   r   rv   )r   r   r   r   pause_readingI  s    z$_UnixReadPipeTransport.pause_readingc             C   s   |  j  j |  j |  j  d  S)N)rt   r   rv   r   )r   r   r   r   resume_readingL  s    z%_UnixReadPipeTransport.resume_readingc             C   s   |  j  s |  j d   n  d  S)N)r~   _close)r   r   r   r   r   O  s    	z_UnixReadPipeTransport.closezFatal error on pipe transportc             C   s   t  | t  rO | j t j k rO |  j j   r~ t j d |  | d d q~ n/ |  j j i | d 6| d 6|  d 6|  j	 d 6 |  j
 |  d  S)Nz%r: %sexc_infoTmessage	exceptionr`   rB   )r<   r*   r/   ZEIOrt   r   r   debugcall_exception_handlerr}   r   )r   r4   r   r   r   r   r   S  s    !z#_UnixReadPipeTransport._fatal_errorc             C   s6   d |  _  |  j j |  j  |  j j |  j |  d  S)NT)r~   rt   r   rv   r   r   )r   r4   r   r   r   r   a  s    	z_UnixReadPipeTransport._closec             C   sD   z |  j  j |  Wd  |  j j   d  |  _ d  |  _  d  |  _ Xd  S)N)r}   connection_lostru   r   rt   )r   r4   r   r   r   r   f  s    		z,_UnixReadPipeTransport._call_connection_losti   )rg   rh   ri   r   r   r   r   r   r   r   r   r   r   r   r   )r   r   r@     s   r@   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 d d d  Z d d d  Z d d   Z   S)rF   Nc                s=  t    j |  | |  j d <| |  _ | |  _ | j   |  _ t j |  j  j	 } t
 j |  } | p t
 j |  p t
 j |  s t d   n  t |  j  | |  _ g  |  _ d |  _ d |  _ | s t j j d  r |  j j |  j |  j  n  |  j j |  j j |   | d  k	 r9|  j j | j d   n  d  S)NrA   z?Pipe transport is only for pipes, sockets and character devicesr   FZaix)r   r   rs   rt   ru   r(   rv   rl   rw   rx   ry   r{   rz   r|   r)   rn   r}   _buffer
_conn_lostr~   sysplatform
startswithr   r   r   r   r   )r   r   rA   rB   rC   rD   r   Z	is_socket)r   r   r   r   s  s*    						z _UnixWritePipeTransport.__init__c             C   s   |  j  j d |  j g } |  j d  k	 r t j |  j j |  j t j	  } | r_ | j
 d  n | j
 d  |  j   } | j
 d |  n | j
 d  d d j |  S)Nzfd=%sr   r   z
bufsize=%sr   z<%s>r   )r   rg   rv   ru   r   r   rt   r   r   ZEVENT_WRITEr   get_write_buffer_sizer   )r   r.   r   rP   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   sL   |  j  j   r" t j d |   n  |  j r> |  j t    n
 |  j   d  S)Nz%r was closed by peer)rt   r   r   r.   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  rH t |  } n  | sR d  S|  j sd |  j r |  j t j	 k r t
 j d  n  |  j d 7_ d  S|  j st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 r9d  S| d k rX| | d   } n  |  j j |  j |  j  n  |  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)r<   bytes	bytearray
memoryviewrZ   reprr   r~   r   Z!LOG_THRESHOLD_FOR_CONNLOST_WRITESr   warningr   rl   writerv   r   r   	Exceptionr   r   rt   Z
add_writer_write_readyr   Z_maybe_pause_protocol)r   r"   nr4   r   r   r   r     s4    *	
z_UnixWritePipeTransport.writec             C   sg  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 r4|  j j |  j  |  j   |  j r0|  j r0|  j j |  j  |  j d   n  d  S| d k rS| | d   } n  |  j j	 |  d  S)N    zData should not be emptyr   z#Fatal write error on pipe transportr   )r   r   rZ   clearrl   r   rv   r   r   r   r   r   rt   remove_writerr   r   Z_maybe_resume_protocolr~   r   r   )r   r"   r   r4   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 sZ |  j j |  j  |  j j |  j d   n  d  S)NT)	r~   ru   rZ   r   rt   r   rv   r   r   )r   r   r   r   	write_eof  s    			z!_UnixWritePipeTransport.write_eofc             C   s   |  j  s |  j   n  d  S)N)r~   r   )r   r   r   r   r     s    	z_UnixWritePipeTransport.closec             C   s   |  j  d   d  S)N)r   )r   r   r   r   abort  s    z_UnixWritePipeTransport.abortzFatal error on pipe transportc             C   s   t  | t t f  rC |  j j   rr t j d |  | d d qr n/ |  j j i | d 6| d 6|  d 6|  j d 6 |  j	 |  d  S)Nz%r: %sr   Tr   r   r`   rB   )
r<   r   ConnectionResetErrorrt   r   r   r   r   r}   r   )r   r4   r   r   r   r   r     s    z$_UnixWritePipeTransport._fatal_errorc             C   sb   d |  _  |  j r( |  j j |  j  n  |  j j   |  j j |  j  |  j j |  j |  d  S)NT)	r~   r   rt   r   rv   r   r   r   r   )r   r4   r   r   r   r     s    		z_UnixWritePipeTransport._closec             C   sD   z |  j  j |  Wd  |  j j   d  |  _ d  |  _  d  |  _ Xd  S)N)r}   r   ru   r   rt   )r   r4   r   r   r   r     s    		z-_UnixWritePipeTransport._call_connection_lost)rg   rh   ri   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   )r   r   rF   p  s   	!	rF   c               @   s   e  Z d  Z d d   Z d S)rI   c       	      K   s   d  } | t  j k r- |  j j   \ } } n  t  j | d | d | d | d | d d d | | |  _ | d  k	 r | j   t | j   d d	 | |  j _	 n  d  S)
NrL   rM   rN   rO   Zuniversal_newlinesFrP   wb	buffering)

subprocessPIPErt   r   Popen_procr   opendetachrM   )	r   r3   rL   rM   rN   rO   rP   rQ   Zstdin_wr   r   r   _start$  s    
z_UnixSubprocessTransport._startN)rg   rh   ri   r   r   r   r   r   rI   "  s   rI   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   rU   r2   r3   r   r   r   rJ   L  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   rU   r   r   r   remove_child_handlerW  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   i  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__p  s    zAbstractChildWatcher.__enter__c             C   s   t     d S)zExit the watcher's contextN)r   )r   abcr   r   r   __exit__v  s    zAbstractChildWatcher.__exit__N)
rg   rh   ri   rj   rJ   r   r   r   r   r   r   r   r   r   r   5  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)rt   )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	 rI |  j j t j  n  | |  _ | d  k	 r | j t j |  j	  |  j
   n  d  S)N)r<   r   ZAbstractEventLooprZ   rt   r   r&   SIGCHLDr6   	_sig_chldr   )r   r   r   r   r   r     s    $	zBaseChildWatcher.attach_loopc             C   sX   y |  j    WnC t k
 rS } z# |  j j i d d 6| d 6 WYd  d  } ~ Xn Xd  S)Nz$Unknown exception in SIGCHLD handlerr   r   )r   r   rt   r   )r   r4   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)rl   WIFSIGNALEDWTERMSIG	WIFEXITEDWEXITSTATUS)r   statusr   r   r   _compute_returncode  s
    z$BaseChildWatcher._compute_returncodeN)
rg   rh   ri   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   rU   r2   r3   r   r   r   rJ     s    z"SafeChildWatcher.add_child_handlerc             C   s/   y |  j  | =d SWn t k
 r* d SYn Xd  S)NTF)r   r8   )r   rU   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   rU   r   r   r   r     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 |  YnE X| d k rr d  S|  j |  } |  j j	   r t j
 d | |  n  y |  j j |  \ } } Wn: t k
 r |  j j	   r t j d | d d n  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)rZ   rl   waitpidWNOHANGChildProcessErrorr   r   r   rt   r   r   r   popr8   )r   r   rU   r   rV   r2   r3   r   r   r   r     s,    		zSafeChildWatcher._do_waitpid)rg   rh   ri   rj   r   r   r   r   rJ   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   	  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     s    zFastChildWatcher.closec          
   C   s'   |  j   |  j d 7_ |  SWd  QXd  S)Nr   )r   r   )r   r   r   r   r     s    
zFastChildWatcher.__enter__c          
   C   sf   |  j  G |  j d 8_ |  j s, |  j r0 d  St |  j  } |  j j   Wd  QXt j 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   s{   |  j  s t d   |  j G y |  j j |  } Wn) t k
 r` | | f |  j | <d  SYn XWd  QX| | | |  d  S)NzMust use the context manager)r   rZ   r   r   r   r8   r   )r   rU   r2   r3   rV   r   r   r   rJ   )  s    
z"FastChildWatcher.add_child_handlerc             C   s/   y |  j  | =d SWn t k
 r* d SYn Xd  S)NTF)r   r8   )r   rU   r   r   r   r   6  s
    
z%FastChildWatcher.remove_child_handlerc             C   s@  x9y t  j d t  j  \ } } Wn t k
 r: d  SYn  X| d k rK d  S|  j |  } |  j  y |  j j |  \ } } WnY t k
 r |  j	 r | |  j
 | <|  j j   r t j d | |  n  w n  d  } Yn& X|  j j   rt j d | |  n  Wd  QX| d  k r)t j d | |  q | | | |  q d  S)Nr   r   z,unknown process %s exited with returncode %sz$process %s exited with returncode %sz8Caught subprocess termination from unknown pid: %d -> %dr$   )rl   r   r   r   r   r   r   r   r8   r   r   rt   r   r   r   r   )r   rU   r   rV   r2   r3   r   r   r   r   =  s6    	
			z FastChildWatcher._do_waitpid_all)rg   rh   ri   rj   r   r   r   r   rJ   r   r   r   r   )r   r   r     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XXXc                s   t    j   d  |  _ d  S)N)r   r   _watcher)r   )r   r   r   r   l  s    z$_UnixDefaultEventLoopPolicy.__init__c          
   C   sc   t  j T |  j d  k rY t   |  _ t t j   t j  rY |  j j |  j	 j
  qY n  Wd  QXd  S)N)r   r   r   r   r<   r   current_thread_MainThreadr   _localrt   )r   r   r   r   _init_watcherp  s    
z)_UnixDefaultEventLoopPolicy._init_watcherc                sN   t    j |  |  j d k	 rJ t t j   t j  rJ |  j j |  n  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   r<   r   r   r   r   )r   r   )r   r   r   r   x  s    z*_UnixDefaultEventLoopPolicy.set_event_loopc             C   s#   |  j  d k r |  j   n  |  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   rH     s    z-_UnixDefaultEventLoopPolicy.get_child_watcherc             C   sM   | d k s! t  | t  s! t  |  j d k	 r@ |  j j   n  | |  _ d S)z$Set the watcher for child processes.N)r<   r   rZ   r   r   )r   rR   r   r   r   set_child_watcher  s    !z-_UnixDefaultEventLoopPolicy.set_child_watcher)rg   rh   ri   rj   r   Z_loop_factoryr   r   r   rH   r   r   r   )r   r   r   h  s   
r   )-rj   r/   rl   r&   r   ry   r   r   r    r   r   r   r   r   r   r	   Z
coroutinesr
   logr   __all__r   ImportErrorr   ZBaseSelectorEventLoopr   hasattrrn   ro   ZReadTransportr@   Z_FlowControlMixinZWriteTransportrF   ZBaseSubprocessTransportrI   r   r   r   r   ZBaseDefaultEventLoopPolicyr   r   r   r   r   r   r   <module>   sN   _F6Ni2