a
    Df1                     @   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m	Z	 ddl
mZmZmZ ddlmZ ddlmZ ddlmZ ddlZddlmZmZmZ ejrdd	lmZ ejZed
ddZdd
ddZdadee ee edddZee d
ddZ G dd de!Z"dS )zUtilities for working with multiple processes, including both forking
the server into multiple processes and managing subprocesses.
    N)hexlify)Future"future_set_result_unless_cancelled%future_set_exception_unless_cancelled)ioloop)PipeIOStream)gen_log)OptionalAnyCallable)Listreturnc                	   C   s\   t du rdS z
t  W S  ty(   Y n0 ztdW S  ttfyL   Y n0 td dS )z1Returns the number of processors on this machine.N   SC_NPROCESSORS_CONFz1Could not detect number of processors; assuming 1)	multiprocessing	cpu_countNotImplementedErrorossysconfAttributeError
ValueErrorr   error r   r   \/nfs/NAS7/SABIOD/METHODE/ermites/ermites_venv/lib/python3.9/site-packages/tornado/process.pyr   1   s    

r   c                  C   sh   dt jvrd S dd l} ztttdd}W n* tyX   tt d t	 A }Y n0 | 
| d S )Nrandomr      i  )sysmodulesr   intr   r   urandomr   timegetpidseed)r   r#   r   r   r   _reseed_randomA   s    
r$   )num_processesmax_restartsr   c           	         sP  t jdkrtd|du rd}tdu s*J | du s:| dkr@t } td|  i  ttt d fdd	}t	| D ]}||}|durp|  S qpd} rBt
 \}}| vrq |}t
|rtd
||t
| n8t
|dkrtd||t
| ntd|| q|d7 }||kr,td||}|dur|S qt d dS )aq  Starts multiple worker processes.

    If ``num_processes`` is None or <= 0, we detect the number of cores
    available on this machine and fork that number of child
    processes. If ``num_processes`` is given and > 0, we fork that
    specific number of sub-processes.

    Since we use processes and not threads, there is no shared memory
    between any server code.

    Note that multiple processes are not compatible with the autoreload
    module (or the ``autoreload=True`` option to `tornado.web.Application`
    which defaults to True when ``debug=True``).
    When using multiple processes, no IOLoops can be created or
    referenced until after the call to ``fork_processes``.

    In each child process, ``fork_processes`` returns its *task id*, a
    number between 0 and ``num_processes``.  Processes that exit
    abnormally (due to a signal or non-zero exit status) are restarted
    with the same id (up to ``max_restarts`` times).  In the parent
    process, ``fork_processes`` calls ``sys.exit(0)`` after all child
    processes have exited normally.

    max_restarts defaults to 100.

    Availability: Unix
    win32zfork not available on windowsNd   r   zStarting %d processes)ir   c                    s.   t  }|dkrt  | a| S |  |< d S d S Nr   )r   forkr$   _task_id)r)   pidchildrenr   r   start_child   s    z#fork_processes.<locals>.start_childz1child %d (pid %d) killed by signal %d, restartingz3child %d (pid %d) exited with status %d, restartingz!child %d (pid %d) exited normallyr   z"Too many child restarts, giving up)r   platform	Exceptionr,   r   r   infor   r	   ranger   waitpopWIFSIGNALEDwarningWTERMSIGWEXITSTATUSRuntimeErrorexit)	r%   r&   r0   r)   idZnum_restartsr-   statusZnew_idr   r.   r   fork_processesS   sV    




r?   c                   C   s   t S )zpReturns the current task id, if any.

    Returns None if this process was not created by `fork_processes`.
    )r,   r   r   r   r   task_id   s    r@   c                   @   s   e Zd ZdZe ZdZi ZeeddddZ	e
egdf dddd	ZdeddddZeddddZeddddZeddddZeeddddZeddddZdS )
Subprocessa   Wraps ``subprocess.Popen`` with IOStream support.

    The constructor is the same as ``subprocess.Popen`` with the following
    additions:

    * ``stdin``, ``stdout``, and ``stderr`` may have the value
      ``tornado.process.Subprocess.STREAM``, which will make the corresponding
      attribute of the resulting Subprocess a `.PipeIOStream`. If this option
      is used, the caller is responsible for closing the streams when done
      with them.

    The ``Subprocess.STREAM`` option and the ``set_exit_callback`` and
    ``wait_for_exit`` methods do not work on Windows. There is
    therefore no reason to use this class instead of
    ``subprocess.Popen`` on that platform.

    .. versionchanged:: 5.0
       The ``io_loop`` argument (deprecated since version 4.1) has been removed.

    FN)argskwargsr   c                 O   s~  t j | _g }g }|dtju rZt \}}||d< |	||f |
| t|| _|dtju rt \}}||d< |	||f |
| t|| _|dtju rt \}	}
|
|d< |	|	|
f |
|
 t|	| _ztj|i || _W n$   |D ]}t| q Y n0 |D ]}t| q&| jj| _dD ]&}t| |sFt| |t| j| qFd | _d | _d S )Nstdinstdoutstderr)rD   rE   rF   )r   ZIOLoopcurrentio_loopgetrA   STREAMr   pipeextendappendr   rD   rE   rF   
subprocessPopenproccloser-   hasattrsetattrgetattr_exit_callback
returncode)selfrB   rC   Zpipe_fdsto_closeZin_rZin_wZout_rZout_wZerr_rZerr_wfdattrr   r   r   __init__   sF    






zSubprocess.__init__)callbackr   c                 C   s*   || _ t  | tj| j< t| j dS )a  Runs ``callback`` when this process exits.

        The callback takes one argument, the return code of the process.

        This method uses a ``SIGCHLD`` handler, which is a global setting
        and may conflict if you have other libraries trying to handle the
        same signal.  If you are using more than one ``IOLoop`` it may
        be necessary to call `Subprocess.initialize` first to designate
        one ``IOLoop`` to run the signal handlers.

        In many cases a close callback on the stdout or stderr streams
        can be used as an alternative to an exit callback if the
        signal handler is causing a problem.

        Availability: Unix
        N)rU   rA   
initialize_waitingr-   _try_cleanup_process)rW   r\   r   r   r   set_exit_callback   s    zSubprocess.set_exit_callbackTzFuture[int])raise_errorr   c                    s*   t   tdd fdd}| |  S )a2  Returns a `.Future` which resolves when the process exits.

        Usage::

            ret = yield proc.wait_for_exit()

        This is a coroutine-friendly alternative to `set_exit_callback`
        (and a replacement for the blocking `subprocess.Popen.wait`).

        By default, raises `subprocess.CalledProcessError` if the process
        has a non-zero exit status. Use ``wait_for_exit(raise_error=False)``
        to suppress this behavior and return the exit status without raising.

        .. versionadded:: 4.2

        Availability: Unix
        N)retr   c                    s,   | dkrrt  t| d n
t |  d S )Nr   unknown)r   CalledProcessErrorr   )rb   futurera   r   r   r\   (  s
    
z*Subprocess.wait_for_exit.<locals>.callback)r   r   r`   )rW   ra   r\   r   re   r   wait_for_exit  s    	
zSubprocess.wait_for_exitr   c                 C   s,   | j r
dS t }|tj| j d| _ dS )a  Initializes the ``SIGCHLD`` handler.

        The signal handler is run on an `.IOLoop` to avoid locking issues.
        Note that the `.IOLoop` used for signal handling need not be the
        same one used by individual Subprocess objects (as long as the
        ``IOLoops`` are each running in separate threads).

        .. versionchanged:: 5.0
           The ``io_loop`` argument (deprecated since version 4.1) has been
           removed.

        Availability: Unix
        NT)_initializedasyncioget_event_loopZadd_signal_handlersignalSIGCHLD_cleanupclsZloopr   r   r   r]   4  s
    zSubprocess.initializec                 C   s(   | j s
dS t }|tj d| _ dS )z Removes the ``SIGCHLD`` handler.NF)rh   ri   rj   Zremove_signal_handlerrk   rl   rn   r   r   r   uninitializeI  s
    zSubprocess.uninitializec                 C   s"   t | j D ]}| | qd S )N)listr^   keysr_   )ro   r-   r   r   r   rm   R  s    zSubprocess._cleanup)r-   r   c                 C   sd   zt |t j\}}W n ty*   Y d S 0 |dkr8d S ||ksDJ | j|}|j|j| d S r*   )	r   waitpidWNOHANGChildProcessErrorr^   r6   rH   Zadd_callback_set_returncode)ro   r-   Zret_pidr>   Zsubprocr   r   r   r_   W  s    zSubprocess._try_cleanup_process)r>   r   c                 C   sp   t jdkrd| _n4t|r,t| | _nt|s:J t|| _| j| j_| j	rl| j	}d | _	|| j d S )Nr'   )
r   r1   rV   r   r7   r9   	WIFEXITEDr:   rP   rU   )rW   r>   r\   r   r   r   rv   c  s    


zSubprocess._set_returncode)T)__name__
__module____qualname____doc__objectrJ   rh   r^   r
   r[   r   r   r`   boolrg   classmethodr]   rp   rm   r_   rv   r   r   r   r   rA      s    ' rA   )N)#r|   ri   r   r   rk   rN   r   r!   binasciir   Ztornado.concurrentr   r   r   Ztornador   Ztornado.iostreamr   Ztornado.logr   typingr	   r
   r   TYPE_CHECKINGr   rd   r   r   r$   r,   r?   r@   r}   rA   r   r   r   r   <module>   s6    `	