B ‡Ž€Æ›Õ0œã@sšdZddlZddlZddlZddlZddlZddlZddlZddlZddl Z ddl Z ddl Z ddl m Z ddl mZddl mZddl mZddl mZdd l mZdd l mZdd l mZdd l mZdd lmZdZe jdkrêedƒ‚dd„ZGdd„dejƒZGdd„dejƒZGdd„dej ej!ƒZ"Gdd„dej#ƒZ$Gdd„dƒZ%Gdd„de%ƒZ&Gdd „d e&ƒZ'Gd!d"„d"e&ƒZ(Gd#d$„d$ej)ƒZ*eZ+e*Z,dS)%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ÚDefaultEventLoopPolicyZwin32z+Signals are not really supported on WindowscCsdS)zDummy signal handler.N©)ÚsignumÚframerrú6/opt/alt/python37/lib/python3.7/asyncio/unix_events.pyÚ_sighandler_noop'srcsÊeZdZdZd)‡fdd„ Z‡fdd„Zdd„Zd d „Zd d „Zd d„Z dd„Z d*dd„Z d+dd„Z d,dd„Z dd„Zd-dddddœdd„Zd.ddddddœdd „Zd!d"„Zd#d$„Zd%d&„Zd'd(„Z‡ZS)/Ú_UnixSelectorEventLoopzdUnix event loop. Adds signal handling and UNIX Domain Socket support to SelectorEventLoop. Ncstƒ |¡i|_dS)N)ÚsuperÚ__init__Ú_signal_handlers)ÚselfÚselector)Ú __class__rrr2s z_UnixSelectorEventLoop.__init__cs^tƒ ¡t ¡s2xFt|jƒD]}| |¡qWn(|jrZtjd|›dt |d|j  ¡dS)NzClosing 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)rrrr6s z_UnixSelectorEventLoop.closecCs"x|D]}|sq| |¡qWdS)N)Ú_handle_signal)rÚdatarrrrÚ_process_self_dataDs z)_UnixSelectorEventLoop._process_self_datac GsLt |¡st |¡rtdƒ‚| |¡| ¡yt |j  ¡¡Wn2t t fk rt}zt t |ƒƒ‚Wdd}~XYnXt |||d¡}||j|<yt |t¡t |d¡Wnšt k rF}zz|j|=|jsyt d¡Wn4t t fk r}zt d|¡Wdd}~XYnX|jtjkr4t d|›dƒ‚n‚Wdd}~XYnXdS)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éÿÿÿÿzset_wakeup_fd(-1) failed: %szsig z cannot be caught)rZ iscoroutineZiscoroutinefunctionÚ TypeErrorÚ _check_signalZ _check_closedÚsignalÚ set_wakeup_fdZ_csockÚfilenoÚ ValueErrorÚOSErrorÚ RuntimeErrorÚstrrZHandlerrÚ siginterruptr ÚinfoÚerrnoÚEINVAL)rr(ÚcallbackÚargsÚexcÚhandleZnexcrrrÚadd_signal_handlerKs0     z)_UnixSelectorEventLoop.add_signal_handlercCs8|j |¡}|dkrdS|jr*| |¡n | |¡dS)z2Internal helper that is the actual signal handler.N)rÚgetZ _cancelledr#Z_add_callback_signalsafe)rr(r=rrrr)xs   z%_UnixSelectorEventLoop._handle_signalc Csä| |¡y |j|=Wntk r*dSX|tjkr>tj}ntj}yt ||¡WnBtk r–}z$|jtj kr„t d|›dƒ‚n‚Wdd}~XYnX|jsàyt  d¡Wn2t tfk rÞ}zt  d|¡Wdd}~XYnXdS)zwRemove a handler for a signal. UNIX only. Return True if a signal handler was removed, False if not. Fzsig z cannot be caughtNr,zset_wakeup_fd(-1) failed: %sT)r.rÚKeyErrorr/ÚSIGINTÚdefault_int_handlerÚSIG_DFLr3r8r9r4r0r2r r7)rr(Zhandlerr<rrrr#‚s(    z,_UnixSelectorEventLoop.remove_signal_handlercCsLt|tƒstd|›ƒ‚d|kr.tjksHntd|›dtj›dƒ‚dS)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. zsig must be an int, not rzsig z out of range(1, ú)N)Ú isinstanceÚintr-r/ÚNSIGr2)rr(rrrr.¢s z$_UnixSelectorEventLoop._check_signalcCst|||||ƒS)N)Ú_UnixReadPipeTransport)rÚpipeÚprotocolÚwaiterÚextrarrrÚ_make_read_pipe_transport®sz0_UnixSelectorEventLoop._make_read_pipe_transportcCst|||||ƒS)N)Ú_UnixWritePipeTransport)rrIrJrKrLrrrÚ_make_write_pipe_transport²sz1_UnixSelectorEventLoop._make_write_pipe_transportc Ës”t ¡‚} | ¡} t||||||||f| |dœ| —Ž} |  |  ¡|j| ¡y| IdHWn,tk r„|  ¡|   ¡IdH‚YnXWdQRX| S)N)rKrL) rÚget_child_watcherÚ create_futureÚ_UnixSubprocessTransportÚadd_child_handlerZget_pidÚ_child_watcher_callbackÚ ExceptionrZ_wait) rrJr;ÚshellÚstdinÚstdoutÚstderrÚbufsizerLÚkwargsÚwatcherrKÚtransprrrÚ_make_subprocess_transport¶s     z1_UnixSelectorEventLoop._make_subprocess_transportcCs| |j|¡dS)N)Zcall_soon_threadsafeZ_process_exited)rÚpidÚ returncoder]rrrrTËsz._UnixSelectorEventLoop._child_watcher_callback)ÚsslÚsockÚserver_hostnameÚssl_handshake_timeoutc Ãs |dkst|tƒst‚|r,|dkrLtdƒ‚n |dk rs(     z,_UnixSelectorEventLoop._sock_sendfile_nativec Cs| ¡} |dk r| |¡| ¡r4| |||¡dS|rd||}|dkrd| |||¡| |¡dSyt | |||¡} Wn*ttfk rÆ|dkr¢|  ||¡|  | |j || ||||||¡ YnHt k rj} z†|dk r| j t jkrt| ƒtk rtdt jƒ} | | _| } |dkrBt d¡} | |||¡| | ¡n| |||¡| | ¡Wdd} ~ XYn¤tk r¤} z| |||¡| | ¡Wdd} ~ XYnjX| dkrÊ| |||¡| |¡nD|| 7}|| 7}|dkrð|  ||¡|  | |j || ||||||¡ dS)Nrzsocket is not connectedzos.sendfile call failed)r1Ú remove_writerÚ cancelledÚ_sock_sendfile_update_fileposZ set_resultrfrÚBlockingIOErrorÚInterruptedErrorÚ_sock_add_cancellation_callbackZ add_writerrˆr3r8ZENOTCONNrmÚConnectionErrorÚ __cause__rrƒZ set_exceptionrU)rrZ registered_fdrbr1rŠr‹rŒÚ total_sentÚfdZsentr<Únew_excr~rrrrˆUs`             z1_UnixSelectorEventLoop._sock_sendfile_native_implcCs|dkrt ||tj¡dS)Nr)rfÚlseekÚSEEK_SET)rr1rŠr—rrrr‘™sz4_UnixSelectorEventLoop._sock_sendfile_update_fileposcs‡‡fdd„}| |¡dS)Ncs&| ¡r"ˆ ¡}|dkr"ˆ |¡dS)Nr,)rr1r)rr˜)rrbrrÚcbžszB_UnixSelectorEventLoop._sock_add_cancellation_callback..cb)Zadd_done_callback)rrrbrœr)rrbrr”sz6_UnixSelectorEventLoop._sock_add_cancellation_callback)N)NN)NN)N)N)N)Ú__name__Ú __module__Ú __qualname__Ú__doc__rrr+r>r)r#r.rMrOr^rTrqr€rŽrˆr‘r”Ú __classcell__rr)rrr,s4 -      *?Drcs„eZdZdZd‡fdd„ Zdd„Zdd„Zd d „Zd d „Zd d„Z dd„Z dd„Z dd„Z dd„Z ddd„Zdd„Zdd„Z‡ZS) rHiNcsÚtƒ |¡||jd<||_||_| ¡|_||_d|_d|_ t   |j¡j }t  |¡s„t  |¡s„t  |¡s„d|_d|_d|_tdƒ‚t  |jd¡|j |jj|¡|j |jj|j|j¡|dk rÖ|j tj|d¡dS)NrIFz)Pipe transport is for pipes/sockets only.)rrÚ_extraÚ_loopÚ_piper1Ú_filenoÚ _protocolÚ_closingÚ_pausedrfr†rzrxÚS_ISFIFOryÚS_ISCHRr2Ú set_blockingÚ call_soonÚconnection_madeÚ _add_readerÚ _read_readyrÚ_set_result_unless_cancelled)rrvrIrJrKrLÚmode)rrrrªs.         z_UnixReadPipeTransport.__init__cCsÀ|jjg}|jdkr | d¡n|jr0| d¡| d|j›¡t|jddƒ}|jdk r|dk rt  ||jt j ¡}|r„| d¡q°| d¡n |jdk r¦| d¡n | d¡d  d   |¡¡S) NÚclosedÚclosingzfd=Ú _selectorÚpollingÚidleÚopenz<{}>ú )rrr¤Úappendr§r¥Úgetattrr£r Ú_test_selector_eventÚ selectorsZ EVENT_READÚformatÚjoin)rr7rrµrrrÚ__repr__Ès"         z_UnixReadPipeTransport.__repr__c Csºyt |j|j¡}WnDttfk r,YnŠtk rX}z| |d¡Wdd}~XYn^X|rl|j  |¡nJ|j   ¡r‚t   d|¡d|_|j  |j¡|j  |jj¡|j  |jd¡dS)Nz"Fatal read error on pipe transportz%r was closed by peerT)rfÚreadr¥Úmax_sizer’r“r3Ú _fatal_errorr¦Z data_receivedr£Ú get_debugr r7r§Ú_remove_readerr¬Z eof_receivedÚ_call_connection_lost)rr*r<rrrr¯Ýs  z"_UnixReadPipeTransport._read_readycCs>|js |jrdSd|_|j |j¡|j ¡r:t d|¡dS)NTz%r pauses reading)r§r¨r£rÄr¥rÃr Údebug)rrrrÚ pause_readingïs   z$_UnixReadPipeTransport.pause_readingcCsB|js |jsdSd|_|j |j|j¡|j ¡r>t d|¡dS)NFz%r resumes reading) r§r¨r£r®r¥r¯rÃr rÆ)rrrrÚresume_reading÷s   z%_UnixReadPipeTransport.resume_readingcCs ||_dS)N)r¦)rrJrrrÚ set_protocolÿsz#_UnixReadPipeTransport.set_protocolcCs|jS)N)r¦)rrrrÚ get_protocolsz#_UnixReadPipeTransport.get_protocolcCs|jS)N)r§)rrrrÚ is_closingsz!_UnixReadPipeTransport.is_closingcCs|js| d¡dS)N)r§Ú_close)rrrrrsz_UnixReadPipeTransport.closecCs.|jdk r*tjd|›t|d|j ¡dS)Nzunclosed transport )r)r¤r$r%r&r)rrrrÚ__del__ s z_UnixReadPipeTransport.__del__úFatal error on pipe transportcCsZt|tƒr4|jtjkr4|j ¡rLtjd||ddn|j ||||j dœ¡|  |¡dS)Nz%r: %sT)Úexc_info)ÚmessageÚ exceptionrprJ) rEr3r8ZEIOr£rÃr rÆÚcall_exception_handlerr¦rÌ)rr<rÐrrrrÂs  z#_UnixReadPipeTransport._fatal_errorcCs(d|_|j |j¡|j |j|¡dS)NT)r§r£rÄr¥r¬rÅ)rr<rrrrÌ sz_UnixReadPipeTransport._closecCs4z|j |¡Wd|j ¡d|_d|_d|_XdS)N)r¦Úconnection_lostr¤rr£)rr<rrrrÅ%s  z,_UnixReadPipeTransport._call_connection_lost)NN)rÎ)rržrŸrÁrr¿r¯rÇrÈrÉrÊrËrrÍrÂrÌrÅr¡rr)rrrH¦s rHcs¢eZdZd%‡fdd„ Zdd„Zdd„Zdd „Zd d „Zd d „Zdd„Z dd„Z dd„Z dd„Z dd„Z dd„Zdd„Zdd„Zd&dd „Zd'd!d"„Zd#d$„Z‡ZS)(rNNc sþtƒ ||¡||jd<||_| ¡|_||_tƒ|_d|_ d|_ t   |j¡j }t |¡}t |¡}t |¡} |s”|s”| s”d|_d|_d|_tdƒ‚t  |jd¡|j |jj|¡| sÈ|ràtj d¡sà|j |jj|j|j¡|dk rú|j tj|d¡dS)NrIrFz?Pipe transport is only for pipes, sockets and character devicesZaix)rrr¢r¤r1r¥r¦Ú bytearrayÚ_bufferÚ _conn_lostr§rfr†rzrxrªr©ryr2r«r£r¬r­r ÚplatformÚ startswithr®r¯rr°) rrvrIrJrKrLr±Zis_charZis_fifoZ is_socket)rrrr2s2         z _UnixWritePipeTransport.__init__cCsØ|jjg}|jdkr | d¡n|jr0| d¡| d|j›¡t|jddƒ}|jdk r¨|dk r¨t  ||jt j ¡}|r„| d¡n | d¡|  ¡}| d|›¡n |jdk r¾| d¡n | d¡d   d  |¡¡S) Nr²r³zfd=r´rµr¶zbufsize=r·z<{}>r¸)rrr¤r¹r§r¥rºr£r r»r¼Z EVENT_WRITEÚget_write_buffer_sizer½r¾)rr7rrµrZrrrr¿Ws&         z _UnixWritePipeTransport.__repr__cCs t|jƒS)N)ÚlenrÕ)rrrrrÙosz-_UnixWritePipeTransport.get_write_buffer_sizecCs6|j ¡rt d|¡|jr*| tƒ¡n| ¡dS)Nz%r was closed by peer)r£rÃr r7rÕrÌÚBrokenPipeError)rrrrr¯rs   z#_UnixWritePipeTransport._read_readyc Cs2t|tttfƒstt|ƒƒ‚t|tƒr.t|ƒ}|s6dS|jsB|jrj|jtj krXt   d¡|jd7_dS|j syt  |j|¡}WnVttfk r d}Yn<tk rÚ}z|jd7_| |d¡dSd}~XYnX|t|ƒkrìdS|dkrt|ƒ|d…}|j |j|j¡|j |7_ | ¡dS)Nz=pipe closed by peer or os.write(pipe, data) raised exception.rrz#Fatal write error on pipe transport)rEÚbytesrÔÚ memoryviewreÚreprrÖr§rZ!LOG_THRESHOLD_FOR_CONNLOST_WRITESr ÚwarningrÕrfÚwriter¥r’r“rUrÂrÚr£Z _add_writerÚ _write_readyZ_maybe_pause_protocol)rr*Únr<rrrrà{s4       z_UnixWritePipeTransport.writec Csö|jstdƒ‚yt |j|j¡}Wnjttfk r:Yn¸tk rŒ}z6|j ¡|j d7_ |j   |j¡|  |d¡Wdd}~XYnfX|t |jƒkrÞ|j ¡|j   |j¡| ¡|jrÚ|j  |j¡| d¡dS|dkrò|jd|…=dS)NzData should not be emptyrz#Fatal write error on pipe transportr)rÕrerfràr¥r’r“rUr'rÖr£Ú_remove_writerrÂrÚZ_maybe_resume_protocolr§rÄrÅ)rrâr<rrrráœs(   z$_UnixWritePipeTransport._write_readycCsdS)NTr)rrrrÚ can_write_eof¶sz%_UnixWritePipeTransport.can_write_eofcCsB|jr dS|jst‚d|_|js>|j |j¡|j |jd¡dS)NT) r§r¤rerÕr£rÄr¥r¬rÅ)rrrrÚ write_eof¹s z!_UnixWritePipeTransport.write_eofcCs ||_dS)N)r¦)rrJrrrrÉÂsz$_UnixWritePipeTransport.set_protocolcCs|jS)N)r¦)rrrrrÊÅsz$_UnixWritePipeTransport.get_protocolcCs|jS)N)r§)rrrrrËÈsz"_UnixWritePipeTransport.is_closingcCs|jdk r|js| ¡dS)N)r¤r§rå)rrrrrËsz_UnixWritePipeTransport.closecCs.|jdk r*tjd|›t|d|j ¡dS)Nzunclosed transport )r)r¤r$r%r&r)rrrrrÍÐs z_UnixWritePipeTransport.__del__cCs| d¡dS)N)rÌ)rrrrÚabortÖsz_UnixWritePipeTransport.abortúFatal error on pipe transportcCsNt|tƒr(|j ¡r@tjd||ddn|j ||||jdœ¡| |¡dS)Nz%r: %sT)rÏ)rÐrÑrprJ) rEr3r£rÃr rÆrÒr¦rÌ)rr<rÐrrrrÂÙs   z$_UnixWritePipeTransport._fatal_errorcCsFd|_|jr|j |j¡|j ¡|j |j¡|j |j|¡dS)NT) r§rÕr£rãr¥r'rÄr¬rÅ)rr<rrrrÌçs  z_UnixWritePipeTransport._closecCs4z|j |¡Wd|j ¡d|_d|_d|_XdS)N)r¦rÓr¤rr£)rr<rrrrÅïs  z-_UnixWritePipeTransport._call_connection_lost)NN)rç)N)rržrŸrr¿rÙr¯ràrárärårÉrÊrËrrÍrærÂrÌrÅr¡rr)rrrN/s"% !   rNc@seZdZdd„ZdS)rRc KsŠd}|tjkrt ¡\}}zPtj|f||||d|dœ|—Ž|_|dk rh| ¡t| ¡d|d|j_ d}Wd|dk r„| ¡| ¡XdS)NF)rVrWrXrYZuniversal_newlinesrZÚwb)Ú buffering) Ú subprocessÚPIPErhZ socketpairÚPopenÚ_procrr·ÚdetachrW) rr;rVrWrXrYrZr[Zstdin_wrrrÚ_startûs   z_UnixSubprocessTransport._startN)rržrŸrïrrrrrRùsrRc@s@eZdZdZdd„Zdd„Zdd„Zdd „Zd d „Zd d „Z dS)raHAbstract 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. cGs tƒ‚dS)aRegister 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)rr_r:r;rrrrS)s z&AbstractChildWatcher.add_child_handlercCs tƒ‚dS)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ð)rr_rrrÚremove_child_handler4sz)AbstractChildWatcher.remove_child_handlercCs tƒ‚dS)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ð)rrvrrrÚ attach_loop<sz AbstractChildWatcher.attach_loopcCs tƒ‚dS)zlClose the watcher. This must be called to make sure that any underlying resource is freed. N)rð)rrrrrFszAbstractChildWatcher.closecCs tƒ‚dS)zdEnter the watcher's context and allow starting new processes This function must return selfN)rð)rrrrÚ __enter__MszAbstractChildWatcher.__enter__cCs tƒ‚dS)zExit the watcher's contextN)rð)rÚaÚbÚcrrrÚ__exit__SszAbstractChildWatcher.__exit__N) rržrŸr rSrñròrrór÷rrrrrs  rc@sDeZdZdd„Zdd„Zdd„Zdd„Zd d „Zd d „Zd d„Z dS)ÚBaseChildWatchercCsd|_i|_dS)N)r£Ú _callbacks)rrrrrZszBaseChildWatcher.__init__cCs| d¡dS)N)rò)rrrrr^szBaseChildWatcher.closecCs tƒ‚dS)N)rð)rÚ expected_pidrrrÚ _do_waitpidaszBaseChildWatcher._do_waitpidcCs tƒ‚dS)N)rð)rrrrÚ_do_waitpid_alldsz BaseChildWatcher._do_waitpid_allcCs~|dkst|tjƒst‚|jdk r<|dkr<|jrÚ _sig_chldrü)rrvrrrrògs zBaseChildWatcher.attach_loopc CsFy | ¡Wn4tk r@}z|j d|dœ¡Wdd}~XYnXdS)Nz$Unknown exception in SIGCHLD handler)rÐrÑ)rürUr£rÒ)rr<rrrrÿ{s  zBaseChildWatcher._sig_chldcCs2t |¡rt |¡ St |¡r*t |¡S|SdS)N)rfÚ WIFSIGNALEDÚWTERMSIGÚ WIFEXITEDÚ WEXITSTATUS)rÚstatusrrrÚ_compute_returncode‡s     z$BaseChildWatcher._compute_returncodeN) rržrŸrrrûrüròrÿrrrrrrøXs røcsPeZdZdZ‡fdd„Zdd„Zdd„Zdd „Zd d „Zd d „Z dd„Z ‡Z S)rad'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) cs|j ¡tƒ ¡dS)N)rùr'rr)r)rrrr s zSafeChildWatcher.closecCs|S)Nr)rrrrró¤szSafeChildWatcher.__enter__cCsdS)Nr)rrôrõrörrrr÷§szSafeChildWatcher.__exit__cGs.|jdkrtdƒ‚||f|j|<| |¡dS)NzICannot add child handler, the child watcher does not have a loop attached)r£r4rùrû)rr_r:r;rrrrSªs  z"SafeChildWatcher.add_child_handlercCs&y |j|=dStk r dSXdS)NTF)rùr@)rr_rrrrñµs z%SafeChildWatcher.remove_child_handlercCs"xt|jƒD]}| |¡q WdS)N)r"rùrû)rr_rrrrü¼sz SafeChildWatcher._do_waitpid_allcCsÒ|dks t‚yt |tj¡\}}Wn(tk rJ|}d}t d|¡Yn0X|dkrXdS| |¡}|j  ¡rzt  d||¡y|j   |¡\}}Wn.t k r¼|j  ¡r¸tjd|ddYnX|||f|žŽdS)Nréÿz8Unknown child process pid %d, will report returncode 255z$process %s exited with returncode %sz'Child watcher got an unexpected pid: %rT)rÏ)rerfÚwaitpidÚWNOHANGÚChildProcessErrorr rßrr£rÃrÆrùÚpopr@)rrúr_rr`r:r;rrrrûÁs,     zSafeChildWatcher._do_waitpid) rržrŸr rrór÷rSrñrürûr¡rr)rrr•s   rcsTeZdZdZ‡fdd„Z‡fdd„Zdd„Zdd „Zd d „Zd d „Z dd„Z ‡Z S)raW'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). cs$tƒ ¡t ¡|_i|_d|_dS)Nr)rrÚ threadingZLockÚ_lockÚ_zombiesÚ_forks)r)rrrrîs  zFastChildWatcher.__init__cs"|j ¡|j ¡tƒ ¡dS)N)rùr'r rr)r)rrrrôs  zFastChildWatcher.closec Cs$|j|jd7_|SQRXdS)Nr)r r)rrrrróùszFastChildWatcher.__enter__c CsT|j8|jd8_|js"|js&dSt|jƒ}|j ¡WdQRXt d|¡dS)Nrz5Caught subprocesses termination from unknown pids: %s)r rr r5r'r rß)rrôrõröZcollateral_victimsrrrr÷ÿs  zFastChildWatcher.__exit__c Gsz|jstdƒ‚|jdkr tdƒ‚|j:y|j |¡}Wn"tk rZ||f|j|<dSXWdQRX|||f|žŽdS)NzMust use the context managerzICannot add child handler, the child watcher does not have a loop attached) rrer£r4r r r r@rù)rr_r:r;r`rrrrS s z"FastChildWatcher.add_child_handlercCs&y |j|=dStk r dSXdS)NTF)rùr@)rr_rrrrñ s z%FastChildWatcher.remove_child_handlerc Csöxðyt dtj¡\}}Wntk r,dSX|dkr:dS| |¡}|jvy|j |¡\}}WnBtk r¢|j rš||j |<|j   ¡r˜t  d||¡wd}YnX|j   ¡r¼t  d||¡WdQRX|dkrÞt  d||¡q|||f|žŽqWdS)Nr,rz,unknown process %s exited with returncode %sz$process %s exited with returncode %sz8Caught subprocess termination from unknown pid: %d -> %d)rfrrr rr rùr r@rr r£rÃr rÆrß)rr_rr`r:r;rrrrü's6      z FastChildWatcher._do_waitpid_all) rržrŸr rrrór÷rSrñrür¡rr)rrräs   rcsHeZdZdZeZ‡fdd„Zdd„Z‡fdd„Zdd „Z d d „Z ‡Z S) Ú_UnixDefaultEventLoopPolicyz:UNIX event loop policy with a watcher for child processes.cstƒ ¡d|_dS)N)rrÚ_watcher)r)rrrrVs z$_UnixDefaultEventLoopPolicy.__init__c CsHtj8|jdkr:tƒ|_tt ¡tjƒr:|j |j j ¡WdQRXdS)N) rr rrrEr Úcurrent_threadÚ _MainThreadròÚ_localr£)rrrrÚ _init_watcherZs  z)_UnixDefaultEventLoopPolicy._init_watchercs6tƒ |¡|jdk r2tt ¡tjƒr2|j |¡dS)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_looprrEr rrrò)rrv)rrrrbs  z*_UnixDefaultEventLoopPolicy.set_event_loopcCs|jdkr| ¡|jS)zzGet the watcher for child processes. If not yet set, a SafeChildWatcher object is automatically created. N)rr)rrrrrPps z-_UnixDefaultEventLoopPolicy.get_child_watchercCs4|dkst|tƒst‚|jdk r*|j ¡||_dS)z$Set the watcher for child processes.N)rErrerr)rr\rrrÚset_child_watcherzs  z-_UnixDefaultEventLoopPolicy.set_child_watcher) rržrŸr rZ _loop_factoryrrrrPrr¡rr)rrrRs   r)-r r8r„rfr¼r/rhrxrêr r r$Úrrrrrrr r r Úlogr Ú__all__r×Ú ImportErrorrZBaseSelectorEventLooprZ ReadTransportrHZ_FlowControlMixinZWriteTransportrNZBaseSubprocessTransportrRrrørrZBaseDefaultEventLoopPolicyrr rrrrrÚsR           | JF=On3