o
    ߤhT                     @   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m	Z	m
Z
 d dlmZ d dlmZmZmZ d dlmZmZ G dd deZdS )    N)
HaltServerAppImportError)Pidfile)socksystemdutil)__version__SERVER_SOFTWAREc                   @   sb  e Zd ZdZdZdZi Zg Zi Zg Z	g Z
dd d D Zedd eeD Zd	d
 Zdd Zdd ZeeeZdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd  Zd!d" Zd#d$ Zd%d& Z d'd( Z!d)d* Z"d+d, Z#d-d. Z$d/d0 Z%dLd3d4Z&d5d6 Z'dMd8d9Z(d:d; Z)d<d= Z*d>d? Z+d@dA Z,dBdC Z-dDdE Z.dFdG Z/dHdI Z0dJdK Z1d1S )NArbiterz
    Arbiter maintain the workers processes alive. It launches or
    kills them if needed. It also manages application reloading
    via SIGHUP/USR2.
          c                 C   s   g | ]	}t td | qS )zSIG%s)getattrsignal).0x r   N/var/www/html/ictaz-jobs/venv/lib/python3.10/site-packages/gunicorn/arbiter.py
<listcomp>,   s    zArbiter.<listcomp>z+HUP QUIT INT TERM TTIN TTOU USR1 USR2 WINCHc                 c   sF    | ]}|d d dkr|d dkrt t||dd   fV  qd S )Nr   SIG_)r   r   lower)r   namer   r   r   	<genexpr>.   s    zArbiter.<genexpr>c                 C   s   t tjd< d | _d | _d | _| | d | _d| _d| _	d| _
d| _d| _t }tjd d  }|dtj ||tjd| _d S )Nr	   Fr   Master)argscwdr   )r	   osenviron_num_workers _last_logged_active_worker_countlogsetuppidfiler   
worker_age
reexec_pid
master_pidmaster_namer   getcwdsysargvinsert
executable	START_CTX)selfappr   r   r   r   r   __init__3   s$   

zArbiter.__init__c                 C   s   | j S N)r   r-   r   r   r   _get_num_workersO   s   zArbiter._get_num_workersc                 C   s    | j }|| _ | j| || d S r0   )r   cfgnworkers_changed)r-   value	old_valuer   r   r   _set_num_workersR   s   zArbiter._set_num_workersc                 C   s   || _ |j| _| jd u r| j|j| _dtjv r| j  | jj| _| jj| _| jj	| _
| jj| _| jj| _| jdddd t| jj dd dD  | jjrf| jj D ]	\}}|tj|< q\| jjrq| j   d S d S )	NGUNICORN_FDzCurrent configuration:
{0}
c                 s   s"    | ]\}}d  ||jV  qdS )z
  {0}: {1}N)formatr5   )r   configr5   r   r   r   r   j   s
    
z Arbiter.setup.<locals>.<genexpr>c                 S   s   | d S N   r   )settingr   r   r   <lambda>n   s    zArbiter.setup.<locals>.<lambda>key)r.   r3   r    logger_classr   r   reopen_filesworker_classaddressworkersnum_workerstimeout	proc_namedebugr:   joinsortedsettingsitemsenvpreload_appwsgi)r-   r.   kvr   r   r   r!   X   s0   









zArbiter.setupc                 C   s  | j dt dtjv rttjd| _| jd | _d| _	t
 | _| jjdurB| jj}| jdkr6|d7 }t|| _| j| j | j|  |   | jsd}t }|rdd| _ttjtj| }n| jr|g }tjdd	D ]	}|t| qrt| j| j || _d	d
d | jD }| j d | j d|| j | j d| jj td| j  t | j!dr| j!"| j| j  | j#|  dS )zS        Initialize the arbiter. Start listening and set pidfile if needed.
        zStarting gunicorn %sGUNICORN_PIDz.2zMaster.2Nr   Tr8   ,c                 S      g | ]}t |qS r   strr   lnrr   r   r   r          z!Arbiter.start.<locals>.<listcomp>zArbiter bootedzListening at: %s (%s)zUsing worker: %sz&READY=1
STATUS=Gunicorn arbiter bootedcheck_config)$r    infor   r   r   intgetr%   rI   r&   getpidpidr3   r"   r   createon_startinginit_signals	LISTENERSr   
listen_fdsrangeSD_LISTEN_FDS_STARTpopsplitappendr   create_socketsrK   rJ   worker_class_str	sd_notifyhasattrrD   r\   
when_ready)r-   pidnamefdsrf   fdlisteners_strr   r   r   startx   sF   



zArbiter.startc                 C   sz   | j D ]}t| qt  | _ }|D ]}t| t| q| j  | jD ]	}t		|| j	 q)t		t	j
| j dS )z        Initialize master signal handling. Most of the signals
        are queued. Child signals only wake up the master.
        N)PIPEr   closepiper   set_non_blockingclose_on_execr    SIGNALSr   SIGCHLDhandle_chld)r-   ppairsr   r   r   rd      s   



zArbiter.init_signalsc                 C   s*   t | jdk r| j| |   d S d S )N   )len	SIG_QUEUErk   wakeupr-   sigframer   r   r   r      s   zArbiter.signalc              
   C   sz  |    td| j  zY|   	 |   | jr| jdnd}|du r2|   | 	  |   q|| j
vr?| jd| q| j
|}t| d| d}|sW| jd| q| jd| |  |   q ttfyu   |   Y dS  ty } z| j|j|jd	 W Y d}~dS d}~w ty     ty   | jjd
dd | d | jdur| j  td Y dS w )zMain master loop.master [%s]Tr   NzIgnoring unknown signal: %sz	handle_%szUnhandled signal: %szHandling signal: %s)reasonexit_statusz Unhandled exception in main loopexc_infoF)ru   r   _setproctitlerI   manage_workersmaybe_promote_masterr   ri   sleepmurder_workers	SIG_NAMESr    r]   r_   r   errorr   StopIterationKeyboardInterrupthaltr   r   r   
SystemExit	Exceptionstopr"   unlinkr(   exit)r-   r   signamehandlerinstr   r   r   run   sP   
 


zArbiter.runc                 C   s   |    |   dS )zSIGCHLD handlingN)reap_workersr   r   r   r   r   r}      s   zArbiter.handle_chldc                 C   s   | j d| j |   dS )z        HUP handling.
        - Reload configuration
        - Start the new worker processes with a new configuration
        - Gracefully shutdown the old worker processes
        zHang up: %sN)r    r]   r&   reloadr1   r   r   r   
handle_hup   s   zArbiter.handle_hupc                 C   s   t )zSIGTERM handling)r   r1   r   r   r   handle_term   s   zArbiter.handle_termc                 C      |  d t)zSIGINT handlingFr   r   r1   r   r   r   
handle_int     
zArbiter.handle_intc                 C   r   )zSIGQUIT handlingFr   r1   r   r   r   handle_quit  r   zArbiter.handle_quitc                 C   s   |  j d7  _ |   dS )zR        SIGTTIN handling.
        Increases the number of workers by one.
        r=   NrG   r   r1   r   r   r   handle_ttin  s   zArbiter.handle_ttinc                 C   s(   | j dkrdS |  j d8  _ |   dS )zR        SIGTTOU handling.
        Decreases the number of workers by one.
        r=   Nr   r1   r   r   r   handle_ttou  s   
zArbiter.handle_ttouc                 C   s   | j   | tj dS )zU        SIGUSR1 handling.
        Kill all workers by sending them a SIGUSR1
        N)r    rC   kill_workersr   SIGUSR1r1   r   r   r   handle_usr1  s   
zArbiter.handle_usr1c                 C   s   |    dS )z        SIGUSR2 handling.
        Creates a new arbiter/worker set as a fork of the current
        arbiter without affecting old workers. Use this to do live
        deployment with the ability to backout a change.
        N)reexecr1   r   r   r   handle_usr2'  s   zArbiter.handle_usr2c                 C   s:   | j jr| jd d| _| tj dS | jd dS )zSIGWINCH handlingzgraceful stop of workersr   z SIGWINCH ignored. Not daemonizedN)	r3   daemonr    r]   rG   r   r   SIGTERMrJ   r1   r   r   r   handle_winch0  s
   zArbiter.handle_winchc                 C   sx   | j dkrd S | j t kr:| jd d| _d| _ | jj| _tjd= | j	d ur0| j	
| jj	 td| j  d S d S )Nr   zMaster has been promoted.r   rT   r   )r%   r   getppidr    r]   r&   r3   rI   r   r"   renamer   r   r1   r   r   r   r   9  s   


zArbiter.maybe_promote_masterc              
   C   sT   zt | jd d W dS  ty) } z|jtjtjfvr W Y d}~dS d}~ww )z;        Wake up the arbiter by writing to the PIPE
        r=      .N)r   writerv   IOErrorerrnoEAGAINEINTR)r-   er   r   r   r   J  s   zArbiter.wakeupNr   c                 C   sl   |    |dkr| jjn| jj}|d| j |dur|d| | jdur)| j  | j|  t	
| dS )z halt arbiter r   zShutting down: %sNz
Reason: %s)r   r    r]   r   r&   r"   r   r3   on_exitr(   r   )r-   r   r   log_funcr   r   r   r   T  s   


zArbiter.haltc              
   C   s   z,t  | jd gg g d}|d sW dS t| jd dr*	 t| jd dsW dS W dS  t jtfyT } zt|d|jd }|tj	tj
fvrI W Y d}~dS d}~w tya   t  Y dS w )zm        Sleep until PIPE is readable or we timeout.
        A readable PIPE means a signal occurred.
        r   g      ?Nr=   r   )selectrv   r   readr   OSErrorr   r   r   r   r   r   r(   r   )r-   readyr   error_numberr   r   r   r   b  s    zArbiter.sleepTc                 C   s   | j | j  kodkn  o| j o| jj }t| j| g | _tj	}|s)tj
}t | jj }| | | jrMt |k rMtd | jrMt |k s?| tj dS )z        Stop workers

        :attr graceful: boolean, If True (the default) workers will be
        killed gracefully  (ie. trying to wait for the current connection)
        r   皙?N)r$   r%   r   r3   
reuse_portr   close_socketsre   r   r   SIGQUITtimegraceful_timeoutr   WORKERSr   SIGKILL)r-   gracefulr   r   limitr   r   r   r   u  s    

zArbiter.stopc                 C   s   | j dkr| jd dS | jdkr| jd dS t }t | _ | j dkr*dS | j|  | jj	
 }t||d< | jrQtt |d< tt| j|d< ndd	d
 | jD |d< t| jd  t| jd | jd | dS )z1        Relaunch the master and workers.
        r   z"USR2 signal ignored. Child exists.Nz#USR2 signal ignored. Parent exists.rT   
LISTEN_PID
LISTEN_FDSrU   c                 s   s    | ]	}t | V  qd S r0   )rX   filenorY   r   r   r   r     s    
z!Arbiter.reexec.<locals>.<genexpr>r8   r   r   )r$   r    warningr%   r   r`   forkr3   pre_execenv_origcopyrX   r   r   re   rK   chdirr,   execvpe)r-   r%   r   r   r   r   r     s*   




zArbiter.reexecc              	   C   sH  | j j}| j jD ]!}|| j jv r| j j| tj|< qztj|= W q ty)   Y qw | j  | 	| j | j
  || j jkre| jD ]}|  qCt| j | j
| _ddd | jD }| j
d| | j |  | jd uru| j  | j jd urt| j j| _| j| j td| j  t| j jD ]}|   q|   d S )NrU   c                 S   rV   r   rW   rY   r   r   r   r     r[   z"Arbiter.reload.<locals>.<listcomp>zListening at: %sr   )r3   rE   rO   r   r   r   KeyErrorr.   r   r!   r    rC   re   rw   r   rl   rK   r]   	on_reloadr"   r   r   rb   ra   r   r   rI   rg   rF   spawn_workerr   )r-   old_addressrR   rZ   rt   r   r   r   r   r     s8   






zArbiter.reloadc              
   C   s   | j sdS t| j }|D ]<\}}zt |j  | j kr!W qW n tt	fy-   Y qw |j
sC| jd| d|_
| |tj q| |tj qdS )z)        Kill unused/idle workers
        NzWORKER TIMEOUT (pid:%s)T)rH   listr   rN   r   	monotonictmplast_updater   
ValueErrorabortedr    criticalkill_workerr   SIGABRTr   )r-   rF   ra   workerr   r   r   r     s"   zArbiter.murder_workersc           	   
   C   sb  z	 t dt j\}}|sW dS | j|krd| _n}|d? }|dkr)| jd|| || jkr6d}t|| j|| jkrCd}t|| j|dkrP| jd|| n0|dkrzt	
|j}W n tyj   d	|}Y nw d
||}|t	jkrz|d7 }| j| | j|d}|sq|j  | j| | q ty } z|jtjkr W Y d}~dS d}~ww )z7        Reap workers to avoid zombie processes
        Tr   r      z#Worker (pid:%s) exited with code %szWorker failed to boot.zApp failed to load.z$Worker (pid:%s) exited with code %s.zcode {}zWorker (pid:{}) was sent {}!z Perhaps out of memory?N)r   waitpidWNOHANGr$   r    r   WORKER_BOOT_ERRORr   APP_LOAD_ERRORr   Signalsr   r   r:   r   r   ri   r   rw   r3   
child_exitr   r   ECHILD)	r-   wpidstatusexitcoder   sig_namemsgr   r   r   r   r   r     sX   




.zArbiter.reap_workersc                 C   s   t | j| jk r|   | j }t|dd d}t || jkr5|d\}}| |tj	 t || jks t |}| j
|krR|| _
| jjd|d|ddd	 d
S d
S )z[        Maintain the number of workers by spawning or killing
        as required.
        c                 S   s
   | d j S r<   )age)wr   r   r   r?   >  s   
 z(Arbiter.manage_workers.<locals>.<lambda>r@   r   z{0} workerszgunicorn.workersgauge)metricr5   mtype)extraN)r   r   rG   spawn_workersrN   rL   ri   r   r   r   r   r    rJ   r:   )r-   rF   ra   r   active_worker_countr   r   r   r   5  s$   


zArbiter.manage_workersc                 C   s"  |  j d7  _ | | j | j| j| j| jd | j| j}| j| | t	
 }|dkr4||_|| j|< |S | j D ]}|j  q9t	 |_zz"td| j  | jd|j | j| | |  td W nQ tyq     ty } z"| jjddd td	| tjd
 tj  t| j W Y d }~n!d }~w ty   | j d |j!st| j" td Y nw W | jd|j z|j  | j#| | W d S  ty   | j$dt%&  Y d S w | jd|j z|j  | j#| | W w  ty   | j$dt%&  Y w w )Nr=   g       @r   zworker [%s]zBooting worker with pid: %sz'Exception while loading the applicationTr   z%s)filezException in worker processr   zWorker exiting (pid: %s)z Exception during worker exit:
%s)'r#   rD   ra   re   r.   rH   r3   r    pre_forkr   r   r   valuesr   rw   r`   r   r   rI   r]   	post_forkinit_processr(   r   r   r   rJ   printstderrflushr   r   	exceptionbootedr   worker_exitr   	traceback
format_exc)r-   r   ra   siblingr   r   r   r   r   K  sn   





zArbiter.spawn_workerc                 C   s8   t | jt| j D ]}|   tdt   q
dS )z        Spawn new workers as needed.

        This is where a worker process leaves the main loop
        of the master process.
        r   N)rg   rG   r   r   r   r   r   random)r-   r   r   r   r   r   y  s   zArbiter.spawn_workersc                 C   s(   t | j }|D ]}| || q	dS )z^        Kill all workers with the signal `sig`
        :attr sig: `signal.SIG*` value
        N)r   r   keysr   )r-   r   worker_pidsra   r   r   r   r     s   zArbiter.kill_workersc                 C   s   z	t || W dS  tyH } z3|jtjkrCz| j|}|j  | j	
| | W W Y d}~dS  ttfyB   Y W Y d}~dS w  d}~ww )zj        Kill a worker

        :attr pid: int, worker pid
        :attr sig: `signal.SIG*` value
         N)r   killr   r   ESRCHr   ri   r   rw   r3   r  r   )r-   ra   r   r   r   r   r   r   r     s   
zArbiter.kill_worker)Nr   )T)2__name__
__module____qualname____doc__r   r   r,   re   r   rv   r   rj   r{   dictdirr   r   r/   r2   r7   propertyrG   r!   ru   rd   r   r}   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r
      s`    	
 1,

		


"77.	r
   )r   r   r
  r   r   r(   r   r  gunicorn.errorsr   r   gunicorn.pidfiler   gunicornr   r   r   r   r	   objectr
   r   r   r   r   <module>   s   