\dmdZddlZddlZddlZddlZddlZddlZddlZddlZddl Z ddl Z ddl Z ddl Z ddl mZddl mZddl mZddl mZddl mZdd l mZdd l mZdd l mZdd l mZdd l mZddlmZdZe jdkr eddZdZGddejZ Gddej!Z"Gddej#ej$Z%Gddej&Z'GddZ(Gdde(Z)Gd d!e(Z*Gd"d#e*Z+Gd$d%e*Z,Gd&d'e(Z-Gd(d)e(Z.Gd*d+ej/Z0e Z1e0Z2dS),z2Selector event loop for Unix with signal handling.N) base_events)base_subprocess) constants) coroutines)events) exceptions)futures)selector_events)tasks) transports)logger)SelectorEventLoopAbstractChildWatcherSafeChildWatcherFastChildWatcherPidfdChildWatcherMultiLoopChildWatcherThreadedChildWatcherDefaultEventLoopPolicywin32z+Signals are not really supported on WindowscdS)zDummy signal handler.N)signumframes $..\python\lib\asyncio\unix_events.py_sighandler_noopr*sDcP tj|S#t$r|cYSwxYwN)oswaitstatus_to_exitcode ValueError)statuss rr"r"/s>(000  s  %%ceZdZdZdfd ZfdZdZdZdZdZ d Z dd Z dd Z dd Z d Z ddddddddZ dddddddddZdZdZdZdZxZS)_UnixSelectorEventLoopzdUnix event loop. Adds signal handling and UNIX Domain Socket support to SelectorEventLoop. NcXt|i|_dSr )super__init___signal_handlers)selfselector __class__s rr)z_UnixSelectorEventLoop.__init__?s) """ "rcNttjs.t |jD]}||dS|jr;tjd|dt||j dSdS)NzClosing the loop z@ on interpreter shutdown stage, skipping signal handlers removalsource) r(closesys is_finalizinglistr*remove_signal_handlerwarningswarnResourceWarningclear)r+sigr-s rr1z_UnixSelectorEventLoop.closeCs   "" .D122 0 0**3//// 0 0$ . I$III.%) ++++ %++-----  . .rc@|D]}|s||dSr )_handle_signal)r+datars r_process_self_dataz)_UnixSelectorEventLoop._process_self_dataQs= ( (F     ' ' ' '  ( (rcRtj|stj|rtd||| t j|j n5#ttf$r!}tt|d}~wwxYwtj|||d}||j|< t j|t"t j|ddS#t$r}|j|=|jsI t jdn3#ttf$r}t'jd|Yd}~nd}~wwxYw|jt*jkrtd|dd}~wwxYw)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()NFset_wakeup_fd(-1) failed: %ssig  cannot be caught)r iscoroutineiscoroutinefunction TypeError _check_signal _check_closedsignal set_wakeup_fd_csockfilenor#OSError RuntimeErrorstrrHandler*r siginterruptrinfoerrnoEINVAL)r+r:callbackargsexchandlenexcs radd_signal_handlerz)_UnixSelectorEventLoop.add_signal_handlerXs  "8 , , 9.x88 9899 9 3  )  !3!3!5!5 6 6 6 6G$ ) ) )s3xx(( ( )xtT::%+c"  M#/ 0 0 0  U + + + + +   %c*( FF(,,,,"G,FFFK >EEEEEEEEFyEL(("#@##@#@#@AAA sZ"+BCB;;C%/D F& F!0EF!E5E0+F!0E55,F!!F&c|j|}|dS|jr||dS||dS)z2Internal helper that is the actual signal handler.N)r*get _cancelledr5_add_callback_signalsafe)r+r:rXs rr<z%_UnixSelectorEventLoop._handle_signalsa&**3// > F   2  & &s + + + + +  ) )& 1 1 1 1 1rc|| |j|=n#t$rYdSwxYw|tjkr tj}n tj} tj||n;#t$r.}|jtj krtd|dd}~wwxYw|jsI tj dn3#ttf$r}tjd|Yd}~nd}~wwxYwdS)zwRemove a handler for a signal. UNIX only. Return True if a signal handler was removed, False if not. FrBrCNr@rAT)rGr*KeyErrorrISIGINTdefault_int_handlerSIG_DFLrMrSrTrNrJr#rrR)r+r:handlerrWs rr5z,_UnixSelectorEventLoop.remove_signal_handlersK 3 %c**   55  &-  0GGnG  M#w ' ' ' '   yEL(("#@##@#@#@AAA   $ A A$R((((( A A A :C@@@@@@@@ Ats< ..A11 B);)B$$B)4C C9C44C9ct|tstd||tjvrt d|dS)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. zsig must be an int, not zinvalid signal number N) isinstanceintrFrI valid_signalsr#)r+r:s rrGz$_UnixSelectorEventLoop._check_signalsa #s## @>s>>?? ? f*,, , ,;c;;<< < - ,rc(t|||||Sr )_UnixReadPipeTransportr+pipeprotocolwaiterextras r_make_read_pipe_transportz0_UnixSelectorEventLoop._make_read_pipe_transports%dD(FEJJJrc(t|||||Sr )_UnixWritePipeTransportrks r_make_write_pipe_transportz1_UnixSelectorEventLoop._make_write_pipe_transports&tT8VUKKKrc Ktj5} | std|} t ||||||||f| |d| } | | |j|  | d{VnN#ttf$rt$r0| | d{VwxYw dddn #1swxYwY| S)NzRasyncio.get_child_watcher() is not activated, subprocess support is not installed.)rnro)rget_child_watcher is_activerN create_future_UnixSubprocessTransportadd_child_handlerget_pid_child_watcher_callback SystemExitKeyboardInterrupt BaseExceptionr1_wait) r+rmrVshellstdinstdoutstderrbufsizerokwargswatcherrntransps r_make_subprocess_transportz1_UnixSelectorEventLoop._make_subprocess_transports % ' ' 7$$&& K #$JKKK''))F-dHdE.3VVW85;5881788F  % %fnn&6&6&*&BF L L L   12        llnn$$$$$$$ #               2 s+A=C8BC8A C((C88C<?C<cH||j|j|dSr )call_soon_threadsafe call_soon_process_exited)r+pid returncoders rr{z._UnixSelectorEventLoop._child_watcher_callbacks% !!$.&2H*UUUUUr)sslsockserver_hostnamessl_handshake_timeoutssl_shutdown_timeoutcK|t|tsJ|r|tdn3|td|td|td||tdtj|}t jt jt jd} |d| ||d{Vn|#| xYw|td|j t jks|j t jkrtd ||d| |||||| d{V\}} || fS) Nz/you have to pass server_hostname when using sslz+server_hostname is only meaningful with ssl1ssl_handshake_timeout is only meaningful with ssl0ssl_shutdown_timeout is only meaningful with ssl3path and sock can not be specified at the same timerFzno path and sock were specified.A UNIX Domain Stream Socket was expected, got )rr)rfrOr#r!fspathsocketAF_UNIX SOCK_STREAM setblocking sock_connectr1familytype_create_connection_transport) r+protocol_factorypathrrrrr transportrms rcreate_unix_connectionz-_UnixSelectorEventLoop.create_unix_connections &*_c*J*J&&&  H& EGGG'* !NOOO$0 GIII#/ FHHH   IKKK9T??D=1CQGGD   '''''d3333333333  | !BCCC v~--I!333 MTMMOOO   U # # #$($E$E "C"7!5%F%7%7777777 8(""s 51C''C>dT)rbacklogrrr start_servingc Kt|trtd||std||std|Z|tdt j|}t jt jt j}|ddvry tj t j |j rt j |n8#t$rYn,t$r } tjd|| Yd} ~ nd} ~ wwxYw ||n#t$rP} || jt&jkr!d|d } tt&j| dd} ~ w|xYw|td |jt jks|jt jkrtd ||d t1j||g|||||} |r.| t7jdd{V| S) Nz*ssl argument must be an SSLContext or Nonerrrr)rz2Unable to check or remove stale UNIX socket %r: %rzAddress z is already in usez-path was not specified, and no sock specifiedrF)rfboolrFr#r!rrrrstatS_ISSOCKst_moderemoveFileNotFoundErrorrMrerrorbindr1rS EADDRINUSErrrrServer_start_servingr sleep) r+rrrrrrrrerrrWmsgservers rcreate_unix_serverz)_UnixSelectorEventLoop.create_unix_servers c4  JHII I ,S ,CEE E +C +BDD D   IKKK9T??D=1CDDDAwk))6}RWT]]%:;;( $(D666L"*+/666666666  $    9 000@T???C!%"2C88dB  | CEEE v~--I!333 MTMMOOO #D4&2B$'2G$8::  !  ! ! # # #+a..  s7)?C)) D5 D>DD"D88 F'A F  F'c K tjn"#t$rtjdwxYw |}n2#tt jf$r}tjdd}~wwxYw tj|j }n"#t$rtjdwxYw|r|n|}|sdS| } | | d|||||d| d{VS)Nzos.sendfile() is not availableznot a regular filer) r!sendfileAttributeErrorr SendfileNotAvailableErrorrLioUnsupportedOperationfstatst_sizerMrw_sock_sendfile_native_impl) r+rfileoffsetcountrLrfsize blocksizefuts r_sock_sendfile_nativez,_UnixSelectorEventLoop._sock_sendfile_native`sN 2 KKK 2 2 26022 2 2 M[[]]FF 78 M M M67KLL L M MHV$$,EE M M M67KLL L M"-EE  1  "" ''T4(.y! E E Eyyyyyys+ 0A A8A33A8<BB5c L|} ||||r||||dS|r9||z }|dkr.||||||dS t j| |||} | dkr.||||||dS|| z }|| z }|||||| |j || |||||| dS#ttf$r?|||||| |j || |||||| YdSt$r} |N| j tjkr9t| t ur#t!dtj} | | _| } |dkrAt%jd} |||||| n2|||||| Yd} ~ dSYd} ~ dSd} ~ wt*t,f$rt.$r7} |||||| Yd} ~ dSd} ~ wwxYw)Nrzsocket is not connectedzos.sendfile call failed)rL remove_writer cancelled_sock_sendfile_update_filepos set_resultr!r_sock_add_cancellation_callback add_writerrBlockingIOErrorInterruptedErrorrMrSENOTCONNrConnectionError __cause__r r set_exceptionr|r}r~)r+r registered_fdrrLrrr total_sentfdsentrWnew_excrs rrz1_UnixSelectorEventLoop._sock_sendfile_native_implwsb [[]]  $   } - - - ==??   . .vvz J J J F   *IA~~2266:NNNz***1 F;r669==DJqyy2266:NNNz*****$d"  (88dCCCD$CS "D& &y*FFFFF[ !12 B B B$44S$??? OOB ?f"E9j B B B B B B ' ' ')I//II_44 *-u~??$'!Q !:-//2266:NNN!!#&&&&2266:NNN!!#&&&&&&&&&'&&&&&-.     # # #  . .vvz J J J   c " " " " " " " " " #s,D''A J#6 J#?CIJ#,,JJ#cV|dkr"tj||tjdSdSNr)r!lseekSEEK_SET)r+rLrrs rrz4_UnixSelectorEventLoop._sock_sendfile_update_fileposs. >> HVVR[ 1 1 1 1 1 >rc@fd}||dS)Nc|r1}|dkr|dSdSdS)Nr@)rrLr)rrr+rs rcbzB_UnixSelectorEventLoop._sock_add_cancellation_callback..cbsR}} +[[]]88&&r***** + +8r)add_done_callback)r+rrrs` ` rrz6_UnixSelectorEventLoop._sock_add_cancellation_callbacks> + + + + + + b!!!!!rr NN)__name__ __module__ __qualname____doc__r)r1r>rZr<r5rGrprsrr{rrrrrr __classcell__r-s@rr&r&9s ###### . . . . .(((+++Z222@ = = =@D(,KKKKAE)-LLLL 04<VVV *.0#4 "&!% 0#0#0#0#0#f*.Gs"&!% GGGGGR.DFDFDFL222"""""""rr&ceZdZdZdfd ZdZdZdZdZdZ d Z d Z d Z d Z d ZejfdZddZdZdZxZS)rjiNct|||jd<||_||_||_||_d|_d|_ tj |jj }tj|sLtj|s8tj|s$d|_d|_d|_t#dtj|jd|j|jj||j|j|j|j|(|jt.j|ddSdS)NrlFz)Pipe transport is for pipes/sockets only.)r(r)_extra_loop_piperL_fileno _protocol_closing_pausedr!rrrS_ISFIFOrS_ISCHRr# set_blockingrconnection_made _add_reader _read_readyr _set_result_unless_cancelled)r+looprlrmrnromoder-s rr)z_UnixReadPipeTransport.__init__sb " F  {{}} !  x %%- d## J d## J T"" JDJDL!DNHII I  e,,, T^;TBBB T-!\4+; = = =   J !E!' / / / / /  rch|sdS|j||dSr ) is_readingrr)r+rrUs rrz"_UnixReadPipeTransport._add_readers7    F r8,,,,,rc"|j o|j Sr )rrr+s rrz!_UnixReadPipeTransport.is_readings<5 $55rc`|jjg}|j|dn|jr|d|d|jt |jdd}|jU|Stj ||jtj }|r|dnH|dn2|j|dn|dd d |S) Nclosedclosingfd= _selectorpollingidleopen<{}> )r-rrappendrrgetattrrr _test_selector_event selectors EVENT_READformatjoin)r+rRr,rs r__repr__z_UnixReadPipeTransport.__repr__s '( :  KK ! ! ! ! ] # KK " " " ($,(()))4:{D99 : !h&:%:$, (<>>G $ I&&&& F#### Z # KK     KK ! ! !}}SXXd^^,,,rc4 tj|j|j}|r|j|dS|jrtj d|d|_ |j |j|j |jj |j |jddS#tt f$rYdSt"$r!}||dYd}~dSd}~wwxYw)N%r was closed by peerTz"Fatal read error on pipe transport)r!readrmax_sizer data_receivedr get_debugrrRr_remove_readerr eof_received_call_connection_lostrrrM _fatal_error)r+r=rWs rrz"_UnixReadPipeTransport._read_ready s5 G74<77D  G,,T22222:''))?K 7>>> $  ))$,777 $$T^%@AAA $$T%?FFFFF !12    DD I I I   c#G H H H H H H H H H IsCD- D6DDc|sdSd|_|j|j|jrt jd|dSdS)NTz%r pauses reading)rrrrrrrdebugrs r pause_readingz$_UnixReadPipeTransport.pause_readingsq    F  !!$,/// :   ! ! 4 L,d 3 3 3 3 3 4 4rc|js|jsdSd|_|j|j|j|jrtjd|dSdS)NFz%r resumes reading) rrrrrrrrrrs rresume_readingz%_UnixReadPipeTransport.resume_reading#sw =    F  t|T-=>>> :   ! ! 5 L-t 4 4 4 4 4 5 5rc||_dSr rr+rms r set_protocolz#_UnixReadPipeTransport.set_protocol+ !rc|jSr r$rs r get_protocolz#_UnixReadPipeTransport.get_protocol. ~rc|jSr rrs r is_closingz!_UnixReadPipeTransport.is_closing1 }rcB|js|ddSdSr )r_closers rr1z_UnixReadPipeTransport.close4s.}  KK       rcv|j1|d|t||jdSdSNzunclosed transport r/rr8r1r+_warns r__del__z_UnixReadPipeTransport.__del__8L : ! E000/$ O O O O J        " !rFatal error on pipe transportc0t|trG|jtjkr2|jrt jd||dn$|j||||j d| |dSNz%r: %sTexc_info)message exceptionrrm) rfrMrSEIOrrrrcall_exception_handlerrr0r+rWr=s rrz#_UnixReadPipeTransport._fatal_error=s sG $ $ ei)?)?z##%% E XtWtDDDD J - -" ! N //    Crcd|_|j|j|j|j|dSNT)rrrrrrr+rWs rr0z_UnixReadPipeTransport._closeKsB  !!$,/// T7=====rc |j||jd|_d|_d|_dS#|jd|_d|_d|_wxYwr rconnection_lostrr1rrDs rrz,_UnixReadPipeTransport._call_connection_lostP  N * *3 / / / J     DJ!DNDJJJ J     DJ!DNDJ     A 0A<rr8)rrrrr)rrrrr r"r&r)r-r1r6r7r6rr0rrrs@rrjrjs(H//////<--- 666---*GGG$444555"""%M    >>> rrjceZdZdfd ZdZdZdZdZdZdZ d Z d Z d Z d Z d ZejfdZdZddZddZdZxZS)rrNcpt||||jd<||_||_||_t|_d|_ d|_ tj |jj }tj|}tj|}tj|} |s(|s&| s$d|_d|_d|_t%dtj|jd|j|jj|| s!|rOt.jds0|j|jj|j|j|(|jt8j|ddSdS)NrlrFz?Pipe transport is only for pipes, sockets and character devicesaix)r(r)rrrLrr bytearray_buffer _conn_lostrr!rrrrrrr#rrrrr2platform startswithrrr r) r+rrlrmrnroris_charis_fifo is_socketr-s rr)z _UnixWritePipeTransport.__init__]s %%%" F {{}} ! {{  x %%-,t$$-%%M$''  E7 Ei EDJDL!DNDEE E  e,,, T^;TBBB  A A)@)@)G)G A J !7!%t/? A A A   J !E!' / / / / /  rc|jjg}|j|dn|jr|d|d|jt |jdd}|j|tj ||jtj }|r|dn|d| }|d|n2|j|dn|dd d |S) Nrrrrrrzbufsize=r r r )r-rrr rrr rr rr EVENT_WRITEget_write_buffer_sizerr)r+rRr,rrs rrz _UnixWritePipeTransport.__repr__sL'( :  KK ! ! ! ! ] # KK " " " ($,(()))4:{D99 : !h&:%:$, (=??G $ I&&&& F###0022G KK,7,, - - - - Z # KK     KK ! ! !}}SXXd^^,,,rc*t|jSr )lenrOrs rrXz-_UnixWritePipeTransport.get_write_buffer_sizes4<   rc|jrtjd||jr#|t dS|dS)Nr)rrrrRrOr0BrokenPipeErrorrs rrz#_UnixWritePipeTransport._read_readysd :   ! ! 7 K/ 6 6 6 <  KK)) * * * * * KKMMMMMrc\t|tttfsJt |t|trt|}|sdS|js|jr;|jtjkrtj d|xjdz c_dS|j s tj |j|}nc#tt f$rd}YnNt"t$f$rt&$r1}|xjdz c_||dYd}~dSd}~wwxYw|t+|krdS|dkrt||d}|j|j|j|xj |z c_ |dS)Nz=pipe closed by peer or os.write(pipe, data) raised exception.rr#Fatal write error on pipe transport)rfbytesrN memoryviewreprrPrr!LOG_THRESHOLD_FOR_CONNLOST_WRITESrwarningrOr!writerrrr|r}r~rrZr _add_writer _write_ready_maybe_pause_protocol)r+r=nrWs rrdz_UnixWritePipeTransport.writes$ : >??KKdKKK dI & & $d##D  F ? dm )"MMM HIII OOq OO F| D HT\400#%56    12       1$!!#'LMMM CII~~Q!$''+ J " "4<1B C C C   ""$$$$$s3CD.#D.=&D))D.c|js Jd tj|j|j}|t |jkr|j|j|j||j r4|j |j| ddS|dkr |jd|=dSdS#ttf$rYdSttf$rt $ri}|j|xjdz c_|j|j||dYd}~dSd}~wwxYw)NzData should not be emptyrrr^)rOr!rdrrZr9r_remove_writer_maybe_resume_protocolrrrrrr|r}r~rPr)r+rhrWs rrfz$_UnixWritePipeTransport._write_readys|777777 %t|44AC %%%% ""$$$ ))$,777++---=5J--dl;;;..t444QL!$$$) !12    DD-.     J J J L   OOq OO J % %dl 3 3 3   c#H I I I I I I I I I  JsC''E>;E>AE99E>cdSrCrrs r can_write_eofz%_UnixWritePipeTransport.can_write_eoftrc|jrdS|jsJd|_|jsA|j|j|j|jddSdSrC)rrrOrrrrrrs r write_eofz!_UnixWritePipeTransport.write_eofsv =  Fz | C J % %dl 3 3 3 J !;T B B B B B C Crc||_dSr r$r%s rr&z$_UnixWritePipeTransport.set_protocolr'rc|jSr r$rs rr)z$_UnixWritePipeTransport.get_protocolr*rc|jSr r,rs rr-z"_UnixWritePipeTransport.is_closingr.rcR|j|js|dSdSdSr )rrrprs rr1z_UnixWritePipeTransport.closes5 : !$- ! NN      " ! ! !rcv|j1|d|t||jdSdSr2r3r4s rr6z_UnixWritePipeTransport.__del__r7rc0|ddSr )r0rs rabortz_UnixWritePipeTransport.aborts Drr8ct|tr2|jrt jd||dn$|j||||jd||dSr:) rfrMrrrrr@rr0rAs rrz$_UnixWritePipeTransport._fatal_errors c7 # # z##%% E XtWtDDDD J - -" ! N //    Crcd|_|jr|j|j|j|j|j|j|j|dSrC) rrOrrjrr9rrrrDs rr0z_UnixWritePipeTransport._closesx < 4 J % %dl 3 3 3  !!$,/// T7=====rc |j||jd|_d|_d|_dS#|jd|_d|_d|_wxYwr rFrDs rrz-_UnixWritePipeTransport._call_connection_lostrHrIrrJr )rrrr)rrXrrdrfrmrpr&r)r-r1r6r7r6rwrr0rrrs@rrrrrZsH#/#/#/#/#/#/J---0!!!!%!%!%F%%%8CCC""" %M     >>>>rrrceZdZdZdS)rxc d}|tjkr5tjdrt j\}} tj|f||||d|d||_|D| t| d||j_ d}|*| | dSdS#|)| | wwxYw)NrMF)rrrruniversal_newlinesrwb) buffering) subprocessPIPEr2rQrRr socketpairPopen_procr1r detachr) r+rVrrrrrrstdin_ws r_startz_UnixSubprocessTransport._start)s JO # # (?(?(F(F # $.00NE7 #)E!vf#('EE=CEEDJ" #'(8(8$'#R#R#R  "  #"w"  #s A$C-DN)rrrrrrrrxrx's#     rrxc<eZdZdZdZdZdZdZdZdZ dZ d S) 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. ct)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. NotImplementedErrorr+rrUrVs rryz&AbstractChildWatcher.add_child_handlerVs"###rct)zRemoves the handler for process 'pid'. The function returns True if the handler was successfully removed, False if there was nothing to remove.rr+rs rremove_child_handlerz)AbstractChildWatcher.remove_child_handleras "###rct)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. rr+rs r attach_loopz AbstractChildWatcher.attach_loopis"###rct)zlClose the watcher. This must be called to make sure that any underlying resource is freed. rrs rr1zAbstractChildWatcher.closess "###rct)zReturn ``True`` if the watcher is active and is used by the event loop. Return True if the watcher is installed and ready to handle process exit notifications. rrs rrvzAbstractChildWatcher.is_activezs"###rct)zdEnter the watcher's context and allow starting new processes This function must return selfrrs r __enter__zAbstractChildWatcher.__enter__s"###rct)zExit the watcher's contextrr+abcs r__exit__zAbstractChildWatcher.__exit__s!###rN) rrrrryrrr1rvrrrrrrr?s, $ $ $$$$$$$$$$$$$$$$ $$$$$rrcHeZdZdZdZdZdZdZdZdZ dZ d Z d Z d S) ra6Child watcher implementation using Linux's pid file descriptors. This child watcher polls process file descriptors (pidfds) to await child process termination. In some respects, PidfdChildWatcher is a "Goldilocks" child watcher implementation. It doesn't require signals or threads, doesn't interfere with any processes launched outside the event loop, and scales linearly with the number of subprocesses launched by the event loop. The main disadvantage is that pidfds are specific to Linux, and only work on recent (5.3+) kernels. c"d|_i|_dSr r _callbacksrs rr)zPidfdChildWatcher.__init__ rc|Sr rrs rrzPidfdChildWatcher.__enter__ rcdSr r)r+exc_type exc_value exc_tracebacks rrzPidfdChildWatcher.__exit__ rcF|jduo|jSr r is_runningrs rrvzPidfdChildWatcher.is_active"z%A$**?*?*A*AArc0|ddSr rrs rr1zPidfdChildWatcher.close rc6|j#|!|jrtjdt|jD]4\}}}|j|tj|5|j ||_dSNzCA loop is being detached from a child watcher with pending handlers) rrr6r7RuntimeWarningvaluesrr!r1r9)r+rpidfd_s rrzPidfdChildWatcher.attach_loops : !dltl M=    ?1133  KE1a J % %e , , , HUOOOO  rc|j|}||d||f|j|<dStj|}|j||j||||f|j|<dSr)rr\r! pidfd_openrr_do_wait)r+rrUrVexistingrs rryz#PidfdChildWatcher.add_child_handlers~?&&s++  #+A;$#>DOC M#&&E J " "5$- = = =#((D#8DOC rcR|j|\}}}|j| t j|d\}}t |}n'#t$rd}tj d|YnwxYwt j ||||g|RdS)NrzJchild process pid %d exit status already read: will report returncode 255) rpoprrr!waitpidr"ChildProcessErrorrrcr1)r+rrrUrVrr$rs rrzPidfdChildWatcher._do_waits $ 3 3C 8 8x !!%((( 8 3**IAv077JJ!   J N.        j(4((((((sA""!BBc |j|\}}}n#t$rYdSwxYw|j|t j|dS)NFT)rrr`rrr!r1)r+rrrs rrz&PidfdChildWatcher.remove_child_handlersn /--c22KE1aa   55  !!%((( ts ! //N) rrrrr)rrrvr1rryrrrrrrrs     BBB   999)))&rrc8eZdZdZdZdZdZdZdZdZ dS) BaseChildWatcherc"d|_i|_dSr rrs rr)zBaseChildWatcher.__init__rrc0|ddSr rrs rr1zBaseChildWatcher.closerrcF|jduo|jSr rrs rrvzBaseChildWatcher.is_activerrctr r)r+ expected_pids r _do_waitpidzBaseChildWatcher._do_waitpid!###rctr rrs r_do_waitpid_allz BaseChildWatcher._do_waitpid_allrrct|t|tjsJ|j#|!|jrt jdt|j$|jtj ||_|;| tj |j | dSdSr)rfrAbstractEventLooprrr6r7rr5rISIGCHLDrZ _sig_chldrrs rrzBaseChildWatcher.attach_loops|z$0HII||| : !dltl M=   : ! J , ,V^ < < <    # #FNDN C C C  " " " " "  rc |dS#ttf$rt$r(}|jd|dYd}~dSd}~wwxYw)N$Unknown exception in SIGCHLD handler)r=r>)rr|r}r~rr@rDs rrzBaseChildWatcher._sig_chlds   " " " " "-.        J - -A //           sAAAN) rrrr)r1rvrrrrrrrrrsBBB$$$$$$###(     rrcFeZdZdZfdZdZdZdZdZdZ dZ xZ 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) cz|jtdSr )rr9r(r1r+r-s rr1zSafeChildWatcher.closes,   rc|Sr rrs rrzSafeChildWatcher.__enter__ rrcdSr rrs rrzSafeChildWatcher.__exit__#rrcH||f|j|<||dSr )rrrs rryz"SafeChildWatcher.add_child_handler&s/ ($/ rc: |j|=dS#t$rYdSwxYwNTFrr`rs rrz%SafeChildWatcher.remove_child_handler,8 $4   55   c^t|jD]}||dSr r4rrrs rrz SafeChildWatcher._do_waitpid_all3s<(( " "C   S ! ! ! ! " "rc|dksJ tj|tj\}}|dkrdSt|}|jrt jd||n)#t$r|}d}t j d|YnwxYw |j |\}}|||g|RdS#t$r7|jrt j d|dYdSYdSwxYw)Nr$process %s exited with returncode %sr8Unknown child process pid %d, will report returncode 255'Child watcher got an unexpected pid: %rTr;) r!rWNOHANGr"rrrrrrcrrr`)r+rrr$rrUrVs rrzSafeChildWatcher._do_waitpid8sa 7*\2:>>KCaxx/77Jz##%% 7 C):777!   CJ NJ       $ -!_0055NHd HS* ,t , , , , , , 3 3 3z##%% 3H"T3333333 3 3 3 3s#"A33#BBC:DD) rrrrr1rrryrrrrrs@rrrs    """ - - - - - - -rrcJeZdZdZfdZfdZdZdZdZdZ dZ xZ 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). cttj|_i|_d|_dSr)r(r) threadingLock_lock_zombies_forksrs rr)zFastChildWatcher.__init__es: ^%%   rc|j|jtdSr )rr9rr(r1rs rr1zFastChildWatcher.closeks@    rch|j5|xjdz c_|cdddS#1swxYwYdS)Nr)rrrs rrzFastChildWatcher.__enter__ps Z   KK1 KK                  s '++c |j5|xjdzc_|js|js ddddSt|j}|jdddn #1swxYwYt jd|dS)Nrz5Caught subprocesses termination from unknown pids: %s)rrrrOr9rrc)r+rrrcollateral_victimss rrzFastChildWatcher.__exit__vs Z " " KK1 KK{ $-   " " " " " " " " "%T]!3!3  M   ! ! ! " " " " " " " " " " " " " " "  C      s A.-A..A25A2c|js Jd|j5 |j|}n(#t$r||f|j|<YddddSwxYw dddn #1swxYwY|||g|RdS)NzMust use the context manager)rrrrr`r)r+rrUrVrs rryz"FastChildWatcher.add_child_handlers{:::::: Z   !]..s33    '/~$                          j(4((((((s1A+6A+A A+AA++A/2A/c: |j|=dS#t$rYdSwxYwrrrs rrz%FastChildWatcher.remove_child_handlerrrc~ tjdtj\}}|dkrdSt|}n#t$rYdSwxYw|j5 |j|\}}|j rtj d||n_#t$rR|j rF||j|<|j rtj d||Ydddd}YnwxYwdddn #1swxYwY|tjd||n |||g|R=)NTr@rrz,unknown process %s exited with returncode %sz8Caught subprocess termination from unknown pid: %d -> %d)r!rrr"rrrrrrrrr`rrrc)r+rr$rrUrVs rrz FastChildWatcher._do_waitpid_alls% 1 < jRZ88 V !88F3F;; %     6 66%)_%8%8%=%=NHdz++--6 %K%(*666 $ $ ${!-7 c*://11:"L*>),j:::! 6 6 6 6 6 6 6 $HHH $ 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6& #Z1111j040000K% 1sR"= A  A DB$40D$A D.D;D=D?DDDD) rrrrr)r1rrryrrrrs@rrr[s       ) ) )(1(1(1(1(1(1(1rrcTeZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z d Zd S)ra~A watcher that doesn't require running loop in the main thread. This implementation registers a SIGCHLD signal handler on instantiation (which may conflict with other code that install own handler for this signal). The solution is safe but it has a significant overhead when handling a big number of processes (*O(n)* each time a SIGCHLD is received). c"i|_d|_dSr )r_saved_sighandlerrs rr)zMultiLoopChildWatcher.__init__s!%rc|jduSr )rrs rrvzMultiLoopChildWatcher.is_actives%T11rc|j|jdStjtj}||jkrtjdn$tjtj|jd|_dS)Nz+SIGCHLD handler was changed by outside code) rr9rrI getsignalrrrrc)r+rds rr1zMultiLoopChildWatcher.closes|   ! ) F"6>22 dn $ $ NH I I I I M&.$*@ A A A!%rc|Sr rrs rrzMultiLoopChildWatcher.__enter__rrcdSr rr+rexc_valexc_tbs rrzMultiLoopChildWatcher.__exit__rrcptj}|||f|j|<||dSr )rget_running_looprr)r+rrUrVrs rryz'MultiLoopChildWatcher.add_child_handlers?&(( $h5 rc: |j|=dS#t$rYdSwxYwrrrs rrz*MultiLoopChildWatcher.remove_child_handlerrrc|jdStjtj|j|_|j%t jdtj|_tjtjddS)NzaPrevious SIGCHLD handler was set by non-Python code, restore to default handler on watcher close.F)rrIrrrrcrcrQrs rrz!MultiLoopChildWatcher.attach_loopsw  ! - F!'v~t~!N!N  ! ) NJ K K K%+^D " FNE22222rc^t|jD]}||dSr rrs rrz%MultiLoopChildWatcher._do_waitpid_alls<(( " "C   S ! ! ! ! " "rcD|dksJ tj|tj\}}|dkrdSt|}d}n+#t$r|}d}t jd|d}YnwxYw |j|\}}}| rt jd||dS|r*| rt j d|||j |||g|RdS#t$rt jd|d YdSwxYw) NrTrrF%Loop %r that handles pid %r is closedrrr;)r!rrr"rrrcrr is_closedrrrr`) r+rrr$r debug_logrrUrVs rrz!MultiLoopChildWatcher._do_waitpidsa *\2:>>KCaxx/77JII!   CJ NJ   III   L#'?#6#6s#;#; D(D~~ LFcRRRRR;!1!1;L!G!-z;;;))(CKdKKKKKK / / / ND / / / / / / / /s#"A%A.-A.2C::!DDc |dS#ttf$rt$rt jddYdSwxYw)NrTr;)rr|r}r~rrc)r+rrs rrzMultiLoopChildWatcher._sig_chld8sy R  " " " " "-.     R R R NAD Q Q Q Q Q Q Q Rs1A  A N)rrrrr)rvr1rrryrrrrrrrrrrs  $&&&222 & & &   333""""#L#L#LJRRRRRrrcbeZdZdZdZdZdZdZdZdZ e j fdZ d Z d Zd Zd Zd S)raAThreaded child watcher implementation. The watcher uses a thread per process for waiting for the process finish. It doesn't require subscription on POSIX signal but a thread creation is not free. The watcher has O(1) complexity, its performance doesn't depend on amount of spawn processes. cFtjd|_i|_dSr) itertoolsr _pid_counter_threadsrs rr)zThreadedChildWatcher.__init__Ns%OA.. rcdSrCrrs rrvzThreadedChildWatcher.is_activeRrnrc.|dSr ) _join_threadsrs rr1zThreadedChildWatcher.closeUs rcdt|jD}|D]}|dS)z%Internal: Join all non-daemon threadscHg|]}||j| Sr)is_alivedaemon.0threads r z6ThreadedChildWatcher._join_threads..Zs@???foo''?06 ?6???rN)r4r rr)r+threadsrs rr z"ThreadedChildWatcher._join_threadsXs]??T]-A-A-C-C(D(D???  F KKMMMM  rc|Sr rrs rrzThreadedChildWatcher.__enter___rrcdSr rrs rrzThreadedChildWatcher.__exit__brrcdt|jD}|r||jdt|dSdS)Nc:g|]}||Sr)rrs rrz0ThreadedChildWatcher.__del__..fs6)))foo'')6)))rz0 has registered but not finished child processesr/)r4r rr-r8)r+r5rs rr6zThreadedChildWatcher.__del__es}))T]-A-A-C-C(D(D)))   ET^UUU!        rctj}tj|jdt |j||||fd}||j|<|dS)Nzwaitpid-T)targetnamerVr) rrrThreadrnextr r start)r+rrUrVrrs rryz&ThreadedChildWatcher.add_child_handlermsp&((!)9'K$t7H2I2I'K'K(,c8T'B)-///$ c rcdSrCrrs rrz)ThreadedChildWatcher.remove_child_handlervs trcdSr rrs rrz ThreadedChildWatcher.attach_loop|rrc|dksJ tj|d\}}t|}|rt jd||n)#t $r|}d}t jd|YnwxYw|rt jd||n|j |||g|R|j |dS)Nrrrrr) r!rr"rrrrrcrrr r)r+rrrUrVrr$rs rrz ThreadedChildWatcher._do_waitpids a 7*\155KC077J~~ 7 C):777!   CJ NJ        >>   H NBD# N N N N %D %hZ G$ G G G G ,'''''sA#BBN)rrrrr)rvr1r rrr6r7r6ryrrrrrrrrAs     %M    (((((rrcBeZdZdZeZfdZdZfdZdZ dZ xZ S)_UnixDefaultEventLoopPolicyz:UNIX event loop policy with a watcher for child processes.cVtd|_dSr )r(r)_watcherrs rr)z$_UnixDefaultEventLoopPolicy.__init__s$  rctj5|j]t|_t jt jur$|j|jj ddddS#1swxYwYdSr ) rrr'rrcurrent_thread main_threadr_localrrs r _init_watcherz)_UnixDefaultEventLoopPolicy._init_watchers \ A A}$ 4 6 6 +--1F1H1HHHM--dk.?@@@  A A A A A A A A A A A A A A A A A AsA%A??BBct||jBtjtjur|j|dSdSdS)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'rr)r*r)r+rr-s rr.z*_UnixDefaultEventLoopPolicy.set_event_loopsl t$$$ M %(**i.C.E.EEE M % %d + + + + + & %EErcF|j||jS)z~Get the watcher for child processes. If not yet set, a ThreadedChildWatcher object is automatically created. )r'r,rs rruz-_UnixDefaultEventLoopPolicy.get_child_watchers& =    }rc|t|tsJ|j|j||_dS)z$Set the watcher for child processes.N)rfrr'r1)r+rs rset_child_watcherz-_UnixDefaultEventLoopPolicy.set_child_watchersC*W6J"K"K = $ M   ! ! ! r) rrrrr& _loop_factoryr)r,r.rur1rrs@rr%r%sDD*MAAA , , , , ,       rr%)3rrSrrr!rrIrrrr2rr6rrrrrr r r r r logr__all__rQ ImportErrorrr"BaseSelectorEventLoopr& ReadTransportrj_FlowControlMixinWriteTransportrrBaseSubprocessTransportrxrrrrrrrBaseDefaultEventLoopPolicyr%rrrrrr=s88     <7 +C D DD   N"N"N"N"N"_BN"N"N"b MMMMMZ5MMM`JJJJJj:(7JJJZ     F   0L$L$L$L$L$L$L$L$^KKKKK,KKK\22222+222jG-G-G-G-G-'G-G-G-Tf1f1f1f1f1'f1f1f1RzRzRzRzRzR0zRzRzRzV(V(V(V(V(/V(V(V(r/ / / / / &"C/ / / d+4r