B
    È S].  ã               @   sþ   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
ddgZdZe d¡ZG dd„ deƒZddd„Zdd„ Zdd„ Zdd„ Zeƒ ZejZejZejZejZdS )é    Né   )Ú
connection)Úprocess)Ú	reduction)Úsemaphore_tracker)Úspawn)ÚutilÚensure_runningÚget_inherited_fdsÚconnect_to_new_processÚset_forkserver_preloadé   Úqc               @   s4   e Zd Zdd„ Zdd„ Zdd„ Zdd„ Zd	d
„ ZdS )Ú
ForkServerc             C   s.   d | _ d | _d | _d | _t ¡ | _dg| _d S )NÚ__main__)Ú_forkserver_addressÚ_forkserver_alive_fdÚ_forkserver_pidÚ_inherited_fdsÚ	threadingZLockÚ_lockÚ_preload_modules)Úself© r   ú+lib/python3.7/multiprocessing/forkserver.pyÚ__init__"   s    
zForkServer.__init__c             C   s&   t dd„ | jD ƒƒstdƒ‚|| _dS )z>Set list of module names to try to load in forkserver process.c             s   s   | ]}t |ƒtkV  qd S )N)ÚtypeÚstr)Ú.0Úmodr   r   r   ú	<genexpr>,   s    z4ForkServer.set_forkserver_preload.<locals>.<genexpr>z&module_names must be a list of stringsN)Úallr   Ú	TypeError)r   Zmodules_namesr   r   r   r   *   s    z!ForkServer.set_forkserver_preloadc             C   s   | j S )z”Return list of fds inherited from parent process.

        This returns None if the current process was not started by fork
        server.
        )r   )r   r   r   r   r
   0   s    zForkServer.get_inherited_fdsc          
   C   sÎ   |   ¡  t|ƒd tkr tdƒ‚t tj¡˜}| | j¡ t 	¡ \}}t 	¡ \}}||| j
t ¡ g}||7 }z<yt ||¡ ||fS    t |¡ t |¡ ‚ Y nX W dt |¡ t |¡ X W dQ R X dS )a;  Request forkserver to create a child process.

        Returns a pair of fds (status_r, data_w).  The calling process can read
        the child process's pid and (eventually) its returncode from status_r.
        The calling process should write to data_w the pickled preparation and
        process data.
        é   ztoo many fdsN)r	   ÚlenÚMAXFDS_TO_SENDÚ
ValueErrorÚsocketÚAF_UNIXZconnectr   ÚosÚpiper   r   Zgetfdr   ZsendfdsÚclose)r   ÚfdsZclientZparent_rÚchild_wÚchild_rZparent_wZallfdsr   r   r   r   8   s&    



z!ForkServer.connect_to_new_processc                s|  | j j t ¡  | jdk	rVt | jtj¡\}}|s8dS t | j¡ d| _	d| _d| _d}| j
rŠddh‰ t d¡}‡ fdd„| ¡ D ƒ}ni }t tj¡Î}t d¡}| |¡ t |d	¡ | ¡  t ¡ \}}ztyV| ¡ |g}	|| ¡ || j
|f; }t ¡ }
|
gt ¡  }|d
|g7 }t |
||	¡}W n   t |¡ ‚ Y nX W dt |¡ X || _	|| _|| _W dQ R X W dQ R X dS )zíMake sure that a fork server is running.

        This can be called from any process.  Note that usually a child
        process will just reuse the forkserver started by its parent, so
        ensure_running() will do nothing.
        NzCfrom multiprocessing.forkserver import main; main(%d, %d, %r, **%r)Ú	main_pathÚsys_pathÚignorec                s   i | ]\}}|ˆ kr||“qS r   r   )r   ÚxÚy)Údesired_keysr   r   ú
<dictcomp>p   s    z-ForkServer.ensure_running.<locals>.<dictcomp>r(   i€  z-c)r   r   r	   r   r)   ÚwaitpidÚWNOHANGr+   r   r   r   r   Zget_preparation_dataÚitemsr'   r(   r   Zarbitrary_addressZbindÚchmodZlistenr*   ÚfilenoZget_executabler   Z_args_from_interpreter_flagsZspawnv_passfds)r   ÚpidZstatusÚcmdÚdataÚlistenerZaddressÚalive_rZalive_wZfds_to_passZexeÚargsr   )r4   r   r	   U   sJ    





zForkServer.ensure_runningN)Ú__name__Ú
__module__Ú__qualname__r   r   r
   r   r	   r   r   r   r   r       s
   r   c             C   s  |rhd|kr8|dk	r8dt  ¡ _zt |¡ W dt  ¡ `X x.|D ]&}yt|ƒ W q> tk
rb   Y q>X q>W t ¡  t	 
¡ \}}t	 |d¡ t	 |d¡ dd„ }tj|tjtji}	dd„ |	 ¡ D ƒ}
t |¡ i }tjtj| d	}t ¡ }| ¡ t_| |tj¡ | |tj¡ | |tj¡ xÊyŒx d
d„ | ¡ D ƒ}|r,P q,W ||krtt	 |d¡dksptdƒ‚t‚||krdt	 |d¡ xØyt	 dt	j ¡\}}W n t!k
rº   P Y nX |dkrÈP | "|d¡}|dk	rPt	 #|¡røt	 $|¡ }n&t	 %|¡std &||¡ƒ‚t	 '|¡}yt(||ƒ W n t)k
rB   Y nX t	 *|¡ nt+ ,d| ¡ qŒW ||kr²| -¡ d 0}t. /|t0d ¡}t1|ƒt0kr®t2d &t1|ƒ¡ƒ‚|^}}}| *¡  t	 3¡ }|dkrVd}zpy<| *¡  | *¡  ||||g}| 4| 5¡ ¡ t6||||
ƒ}W n. t7k
rB   t8j9t8 :¡ Ž  t8j; <¡  Y nX W dt	 =|¡ X nRyt(||ƒ W n t)k
rz   Y nX |||< t	 *|¡ x|D ]}t	 *|¡ q”W W dQ R X W n4 t>k
rè } z|j?t?j@krØ‚ W dd}~X Y nX q&W W dQ R X W dQ R X dS )zRun forkserver.r   NTFc              W   s   d S )Nr   )Z_unusedr   r   r   Úsigchld_handler§   s    zmain.<locals>.sigchld_handlerc             S   s   i | ]\}}t   ||¡|“qS r   )Úsignal)r   ÚsigÚvalr   r   r   r5   ±   s   zmain.<locals>.<dictcomp>)r:   c             S   s   g | ]\}}|j ‘qS r   )Zfileobj)r   ÚkeyZeventsr   r   r   ú
<listcomp>Å   s    zmain.<locals>.<listcomp>r   ó    zNot at EOF?i   éÿÿÿÿr   zChild {0:n} status is {1:n}z.forkserver: waitpid returned unexpected pid %dzToo many ({0:n}) fds to send)Ar   Zcurrent_processZ_inheritingr   Zimport_main_pathÚ
__import__ÚImportErrorr   Z_close_stdinr)   r*   Úset_blockingrE   ÚSIGCHLDÚSIGINTÚSIG_IGNr8   Úset_wakeup_fdr'   r(   Ú	selectorsZDefaultSelectorZgetsocknameÚ_forkserverr   ÚregisterZ
EVENT_READZselectÚreadÚAssertionErrorÚ
SystemExitr6   r7   ÚChildProcessErrorÚpopÚWIFSIGNALEDÚWTERMSIGÚ	WIFEXITEDÚformatÚWEXITSTATUSÚwrite_signedÚBrokenPipeErrorr+   ÚwarningsÚwarnZacceptr   Zrecvfdsr%   r$   ÚRuntimeErrorÚforkÚextendÚvaluesÚ
_serve_oneÚ	ExceptionÚsysÚ
excepthookÚexc_infoÚstderrÚflushÚ_exitÚOSErrorÚerrnoZECONNABORTED)Zlistener_fdr?   Zpreloadr/   r0   ÚmodnameZsig_rZsig_wrD   ÚhandlersZold_handlersZ	pid_to_fdr>   ZselectorZrfdsr;   Ústsr-   Ú
returncodeÚsr,   r.   ÚcodeÚ
unused_fdsÚfdÚer   r   r   Úmain’   sÂ    

















r{   c             C   sd   t  d¡ x | ¡ D ]\}}t   ||¡ qW x|D ]}t |¡ q2W |^t_tj_	t_
t | ¡}|S )NrK   )rE   rR   r8   r)   r+   rT   r   r   Z_semaphore_trackerZ_fdr   r   Ú_main)r.   r,   rx   rs   rF   rG   ry   rw   r   r   r   rh     s    


rh   c             C   sR   d}t j}x8t|ƒ|k rBt | |t|ƒ ¡}|s8tdƒ‚||7 }qW t  |¡d S )NrJ   zunexpected EOFr   )ÚSIGNED_STRUCTÚsizer$   r)   rV   ÚEOFErrorZunpack)ry   r=   Úlengthrv   r   r   r   Úread_signed2  s    r   c             C   s@   t  |¡}x0|r:t | |¡}|dkr,tdƒ‚||d … }qW d S )Nr   zshould not get here)r}   Zpackr)   Úwriterd   )ry   ÚnÚmsgÚnbytesr   r   r   r`   <  s    
r`   )NN) rq   r)   rS   rE   r'   Zstructrj   r   rb   Ú r   r   Úcontextr   r   r   r   Ú__all__r%   ZStructr}   Úobjectr   r{   rh   r   r`   rT   r	   r
   r   r   r   r   r   r   Ú<module>   s:   
r
 
