
    Mh1                     D   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        rdd	lmZ ej        Zd
efdZddZda	 ddee         dee         d
efdZd
ee         fdZ  G d d          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                      t           dS 	 t          j                    S # t          $ r Y nw xY w	 t          j        d          S # t
          t          f$ r Y nw xY wt          j        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     O/var/www/html/test/jupyter/venv/lib/python3.11/site-packages/tornado/process.pyr   r   1   s    q(***   z/000J'   MEFFF1s    
++A AAc                  H   dt           j        vrd S dd l} 	 t          t	          t          j        d                    d          }nG# t          $ r: t          t          j                    dz            t          j	                    z  }Y nw xY w| 
                    |           d S )Nrandomr      i  )sysmodulesr   intr   r   urandomr   timegetpidseed)r   r&   s     r   _reseed_randomr'   A   s    s{""MMM
572:b>>**B// 5 5 549;;%&&45
KKs   /A AB
	B
num_processesmax_restartsc                 R  	 t           j        dk    rt          d          |d}t          J | | dk    rt	                      } t          j        d|            i 	dt          dt          t                   f	fd	}t          |           D ]} ||          }||c S d}	rt          j                    \  }}|	vr	                    |          }t          j        |          r*t          j        d
||t          j        |                     nYt          j        |          dk    r*t          j        d||t          j        |                     nt          j        d||           |dz  }||k    rt#          d           ||          }||S 	t          j        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                 h    t          j                    }|dk    rt                       | a| S | |<   d S Nr   )r   forkr'   _task_id)r-   pidchildrens     r   start_childz#fork_processes.<locals>.start_child   s;    gii!88HHHSM4r   z1child %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	Exceptionr1   r   r	   infor"   r
   ranger   waitpopWIFSIGNALEDwarningWTERMSIGWEXITSTATUSRuntimeErrorexit)
r(   r)   r4   r-   idnum_restartsr2   statusnew_idr3   s
            @r   fork_processesrE   S   s   < |w 7888  2 2!L(-888H
s 
x} 
 
 
 
 
 
 =!!  [^^>III L
 giiVh\\#>&!! 	OCF##	    ^F##q((OEv&&	    L<b#FFF,&&CDDDRM7  @ HQKKKKKr   c                      t           S )zpReturns the current task id, if any.

    Returns None if this process was not created by `fork_processes`.
    )r1   r   r   r   task_idrG      s	     Or   c                       e Zd ZdZ e            ZdZi ZdededdfdZ	de
egdf         ddfd	ZddeddfdZedd            Zedd            Zedd            Zededdfd            Zdeddf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.

    Fargskwargsr   Nc           	         t           j                                        | _        g }g }|                    d          t
          j        u r[t          j                    \  }}||d<   |	                    ||f           |
                    |           t          |          | _        |                    d          t
          j        u r[t          j                    \  }}||d<   |	                    ||f           |
                    |           t          |          | _        |                    d          t
          j        u r[t          j                    \  }	}
|
|d<   |	                    |	|
f           |
                    |
           t          |	          | _        	 t          j        |i || _        n#  |D ]}t          j        |            xY w|D ]}t          j        |           | j        j        | _        dD ]6}t)          | |          s$t+          | |t-          | j        |                     7d | _        d | _        d S )Nstdinstdoutstderr)rM   rN   rO   )r   IOLoopcurrentio_loopgetrI   STREAMr   pipeextendappendr   rM   rN   rO   
subprocessPopenproccloser2   hasattrsetattrgetattr_exit_callback
returncode)selfrJ   rK   pipe_fdsto_closein_rin_wout_rout_werr_rerr_wfdattrs                r   __init__zSubprocess.__init__   s$   },,.. ::g*"333JD$"F7OOOT4L)))OOD!!!%d++DJ::h:#444799LE5$F8OOUEN+++OOE"""&u--DK::h:#444799LE5$F8OOUEN+++OOE"""&u--DK	"($9&99DII	   	 	BHRLLLL9=1 	> 	>D4&& >dGDIt$<$<==="s   F4 4Gcallbackc                     || _         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)r_   rI   
initialize_waitingr2   _try_cleanup_process)ra   rm   s     r   set_exit_callbackzSubprocess.set_exit_callback   sI    " '(,
DH%''11111r   Traise_errorzFuture[int]c                 p    t                      dt          ddff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
        retr   Nc                 x    | dk    r"r t          t          | d                     d S t          |            d S )Nr   unknown)r   CalledProcessErrorr   )ru   futurers   s    r   rm   z*Subprocess.wait_for_exit.<locals>.callback(  sT    axxKx5.sI>>     363?????r   )r   r"   rr   )ra   rs   rm   ry   s    ` @r   wait_for_exitzSubprocess.wait_for_exit  sd    $ 	@# 	@$ 	@ 	@ 	@ 	@ 	@ 	@ 	@ 	x(((r   c                     | j         rdS t          j                    }|                    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_loopadd_signal_handlersignalSIGCHLD_cleanupclsloops     r   ro   zSubprocess.initialize4  sJ      	F%''===r   c                     | j         sdS t          j                    }|                    t          j                   d| _         dS )z Removes the ``SIGCHLD`` handler.NF)r|   r}   r~   remove_signal_handlerr   r   r   s     r   uninitializezSubprocess.uninitializeI  sF      	F%''""6>222 r   c                     t          | j                                                  D ]}|                     |           d S N)listrp   keysrq   )r   r2   s     r   r   zSubprocess._cleanupR  sH    ))++,, 	* 	*C$$S))))	* 	*r   r2   c                    	 t          j        |t           j                  \  }}n# t          $ r Y d S w xY w|dk    rd S ||k    sJ | j                            |          }|j                            |j        |           d S r/   )	r   waitpidWNOHANGChildProcessErrorrp   r:   rR   add_callback_set_returncode)r   r2   ret_pidrC   subprocs        r   rq   zSubprocess._try_cleanup_processW  s    	 jbj99OGVV  	 	 	FF	a<<F#~~~~,""3''$$W%<fEEEEEs   "% 
33rC   c                 b   t           j        dk    rd| _        n^t          j        |          rt          j        |           | _        n/t          j        |          sJ t          j        |          | _        | j        | j        _        | j	        r | j	        }d | _	         || j                   d S d S )Nr+   )
r    r5   r`   r   r;   r=   	WIFEXITEDr>   rZ   r_   )ra   rC   rm   s      r   r   zSubprocess._set_returncodec  s    <7"" DOO~f%% 9#%;v#6#6"6|F+++++"$."8"8  $	 	&*H"&DHT_%%%%%	& 	&r   )Tr   N)__name__
__module____qualname____doc__objectrT   r|   rp   r   rl   r   r"   rr   boolrz   classmethodro   r   r   rq   r   r   r   r   rI   rI      sj        * VXXFLH%c %S %T % % % %N2(C5$;*? 2D 2 2 2 2,      @       [ ( ! ! ! [! * * * [* 	Fs 	Ft 	F 	F 	F [	F&c &d & & & & & &r   rI   r   r   )"r   r}   r   r   r   rX   r    r$   binasciir   tornado.concurrentr   r   r   tornador   tornado.iostreamr   tornado.logr	   typingr
   r   r   TYPE_CHECKINGr   rx   r"   r   r'   r1   rE   rG   rI   r   r   r   <module>r      s      				          



                
       ) ) ) ) ) )        * * * * * * * * * *	   2 3          AE] ]C=]08]] ] ] ]@#    w& w& w& w& w& w& w& w& w& w&r   