a
    ¯|òf)P  ã                   @   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   úJD:\Projects\storyit_web\backend\venv\Lib\site-packages\gunicorn/arbiter.pyÚ
<listcomp>,   s   ÿzArbiter.<listcomp>z+HUP QUIT INT TERM TTIN TTOU USR1 USR2 WINCHc                 c   sD   | ]<}|d d… dkr|d dkrt t|ƒ|dd …  ¡ fV  qd S )Nr   Z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 r/   )r   ÚcfgZ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rÌ| jj ¡ D ]\}}|tj|< q¸| jjrÞ| j  ¡  d S )	NÚGUNICORN_FDzCurrent configuration:
{0}Ú
c                 s   s    | ]\}}d   ||j¡V  qdS )z
  {0}: {1}N)Úformatr3   )r   Úconfigr3   r   r   r   r   j   s   ÿz Arbiter.setup.<locals>.<genexpr>c                 S   s   | d S ©Né   r   )Zsettingr   r   r   Ú<lambda>n   ó    zArbiter.setup.<locals>.<lambda>©Úkey)r-   r2   r   Zlogger_classr   r   Úreopen_filesÚworker_classÚaddressÚworkersÚnum_workersÚtimeoutÚ	proc_nameÚdebugr8   ÚjoinÚsortedÚsettingsÚitemsÚenvZpreload_appZwsgi)r,   r-   ÚkÚvr   r   r   r    X   s.    









ÿýÿ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r„| jj}| jdkrl|d7 }t|ƒ| _| j | j¡ | j | ¡ |  ¡  | jsd}t ¡ }|rÊd| _ttjtj| ƒ}n0| jrúg }tj d¡ d	¡D ]}| t|ƒ¡ qæt | 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   Tr6   ú,c                 S   s   g | ]}t |ƒ‘qS r   ©Ústr©r   Úlr   r   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$   rF   r%   ÚgetpidÚpidr2   r!   r   ÚcreateZon_startingÚinit_signalsÚ	LISTENERSr   Ú
listen_fdsÚrangeZSD_LISTEN_FDS_STARTÚpopÚsplitÚappendr   Úcreate_socketsrH   rG   Zworker_class_strZ	sd_notifyÚhasattrrA   rU   Z
when_ready)r,   ZpidnameZfdsr^   Ú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	¡ qRt	 	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   Zset_non_blockingZclose_on_execr   ÚSIGNALSr   ZSIGCHLDÚhandle_chld)r,   ÚpÚpairÚsr   r   r   r\   ©   s    



zArbiter.init_signalsc                 C   s&   t | jƒdk r"| j |¡ |  ¡  d S )Né   )ÚlenÚ	SIG_QUEUErb   Úwakeup©r,   ÚsigÚframer   r   r   r   ¿   s    zArbiter.signalc              
   C   s†  |   ¡  t d| j ¡ z´|  ¡  |  ¡  | jr<| j d¡nd}|du rb|  ¡  |  	¡  |  ¡  q"|| j
vr|| j d|¡ q"| j
 |¡}t| d| dƒ}|s¬| j d|¡ q"| j d|¡ |ƒ  |  ¡  q"W n´ ttfyê   |  ¡  Y n˜ ty  } z| j|j|jd W Y d}~njd}~0  ty4   ‚ Y nN ty€   | jjd	d
d |  d¡ | jdurr| j ¡  t d¡ Y n0 dS )zMain master loop.úmaster [%s]r   NzIgnoring unknown signal: %sz	handle_%szUnhandled signal: %szHandling signal: %s)ÚreasonÚexit_statusz Unhandled exception in main loopT©Úexc_infoFéÿÿÿÿ)rg   r   Ú_setproctitlerF   Úmanage_workersÚmaybe_promote_masterrr   r`   ÚsleepÚmurder_workersÚ	SIG_NAMESr   rV   rX   r   Úerrorrs   ÚStopIterationÚKeyboardInterruptÚhaltr   rx   ry   Ú
SystemExitÚ	ExceptionÚstopr!   Úunlinkr'   Úexit)r,   ru   ZsignameÚhandlerÚinstr   r   r   ÚrunÄ   sH    
&ÿ

zArbiter.runc                 C   s   |   ¡  |  ¡  dS )zSIGCHLD handlingN)Úreap_workersrs   rt   r   r   r   rl   ð   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   rV   r%   Úreloadr0   r   r   r   Ú
handle_hupõ   s    zArbiter.handle_hupc                 C   s   t ‚dS )zSIGTERM handlingN)r„   r0   r   r   r   Úhandle_termÿ   s    zArbiter.handle_termc                 C   s   |   d¡ t‚dS )zSIGINT handlingFN©r‰   r„   r0   r   r   r   Ú
handle_int  s    
zArbiter.handle_intc                 C   s   |   d¡ t‚dS )zSIGQUIT handlingFNr“   r0   r   r   r   Úhandle_quit  s    
zArbiter.handle_quitc                 C   s   |  j d7  _ |  ¡  dS )zR        SIGTTIN handling.
        Increases the number of workers by one.
        r;   N©rD   r~   r0   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–   r0   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   r@   Úkill_workersr   ZSIGUSR1r0   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)Úreexecr0   r   r   r   Úhandle_usr2'  s    zArbiter.handle_usr2c                 C   s8   | j jr(| j d¡ d| _|  tj¡ n| j d¡ dS )zSIGWINCH handlingzgraceful stop of workersr   z SIGWINCH ignored. Not daemonizedN)	r2   Údaemonr   rV   rD   r™   r   ÚSIGTERMrG   r0   r   r   r   Úhandle_winch0  s
    zArbiter.handle_winchc                 C   st   | j dkrd S | j t ¡ krp| j d¡ d| _d| _ | jj| _tjd= | j	d ur`| j	 
| jj	¡ t d| j ¡ d S )Nr   zMaster has been promoted.r   rO   rw   )r$   r   Úgetppidr   rV   r%   r2   rF   r   r!   Úrenamer   r}   r0   r   r   r   r   9  s    


zArbiter.maybe_promote_masterc              
   C   sT   zt  | jd d¡ W n8 tyN } z |jtjtjfvr:‚ W Y d}~n
d}~0 0 dS )z;        Wake up the arbiter by writing to the PIPE
        r;   ó   .N)r   Úwriterh   ÚIOErrorÚerrnoÚEAGAINÚEINTR)r,   Úer   r   r   rs   J  s
    zArbiter.wakeupNr   c                 C   s\   |   ¡  | j d| j¡ |dur.| j d|¡ | jdurB| j ¡  | j | ¡ t 	|¡ dS )z halt arbiter zShutting down: %sNz
Reason: %s)
r‰   r   rV   r%   r!   rŠ   r2   Zon_exitr'   r‹   )r,   rx   ry   r   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<q(W nf t jtfyŒ } z0t|d|jd ƒ}|tj	tj
fvrx‚ W Y d}~n"d}~0  ty¤   t ¡  Y n0 dS )zm        Sleep until PIPE is readable or we timeout.
        A readable PIPE means a signal occurred.
        r   g      ð?Nr;   r¥   )Úselectrh   r   Úreadrƒ   ÚOSErrorr   r   r¥   r¦   r§   r…   r'   r‹   )r,   Úreadyr¨   Zerror_numberr   r   r   r€   _  s    zArbiter.sleepTc                 C   sš   | j | j  kodkn  o,| j o,| jj }t | j|¡ g | _tj	}|sRtj
}t ¡ | jj }|  |¡ | jrŠt ¡ |k rŠt d¡ ql|  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   r2   Ú
reuse_portr   Zclose_socketsr]   r   rž   ZSIGQUITÚtimeZgraceful_timeoutr™   ÚWORKERSr€   ÚSIGKILL)r,   ZgracefulrŠ   ru   Úlimitr   r   r   r‰   r  s    ÿý
zArbiter.stopc                 C   sê   | j dkr| j d¡ dS | jdkr4| j d¡ dS t ¡ }t ¡ | _ | j dkrTdS | j | ¡ | jj	 
¡ }t|ƒ|d< | jr¢t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.rO   Z
LISTEN_PIDZ
LISTEN_FDSrP   c                 s   s   | ]}t | ¡ ƒV  qd S r/   )rR   ÚfilenorS   r   r   r   r   §  s   z!Arbiter.reexec.<locals>.<genexpr>r6   r   r   )r#   r   Úwarningr$   r   rY   Úforkr2   Zpre_execÚenv_origÚcopyrR   r   rq   r]   rH   Úchdirr+   Úexecvpe)r,   r$   r   r   r   r   r›     s*    




ÿzArbiter.reexecc              	   C   sN  | j j}| j jD ]D}|| j jv r4| j j| tj|< qztj|= W q tyR   Y q0 q| j ¡  |  	| j¡ | j
 ¡  || j jkrÌ| jD ]}| ¡  qˆt | j | j
¡| _d dd„ | jD ƒ¡}| j
 d|¡ | j  | ¡ | jd urì| j ¡  | j jd urt| j jƒ| _| j | j¡ t d| j ¡ t| j jƒD ]}|  ¡  q2|  ¡  d S )NrP   c                 S   s   g | ]}t |ƒ‘qS r   rQ   rS   r   r   r   r   Í  r=   z"Arbiter.reload.<locals>.<listcomp>zListening at: %srw   )r2   rB   rL   r¶   r   r   ÚKeyErrorr-   r   r    r   r@   r]   ri   r   rc   rH   rV   Z	on_reloadr!   rŠ   r   r[   rZ   r   r}   rF   r_   rC   Úspawn_workerr~   )r,   Zold_addressrM   rT   rf   r   r   r   r   r   ¯  s6    





zArbiter.reloadc              
   C   sž   | j s
dS t| j ¡ ƒ}|D ]|\}}z t ¡ |j ¡  | j krBW qW n ttfy^   Y qY n0 |j	sŠ| j
 d|¡ d|_	|  |tj¡ q|  |tj¡ qdS )z)        Kill unused/idle workers
        NzWORKER TIMEOUT (pid:%s)T)rE   Úlistr°   rK   r¯   ÚtmpZlast_updater«   Ú
ValueErrorZabortedr   ÚcriticalÚkill_workerr   ÚSIGABRTr±   )r,   rC   rZ   Úworkerr   r   r   r   æ  s    
zArbiter.murder_workersc              
   C   sð   z¸t  dt j¡\}}|sq¶| j|kr,d| _q|d? }|| jkrNd}t|| jƒ‚|| jkrhd}t|| jƒ‚t  |¡rˆ| j 	d|t  
|¡¡ | j |d¡}|sœq|j ¡  | j | |¡ qW n2 tyê } z|jtjkrÖ‚ W Y d}~n
d}~0 0 dS )z7        Reap workers to avoid zombie processes
        r|   r   é   zWorker failed to boot.zApp failed to load.z2Worker with pid %s was terminated due to signal %sN)r   ÚwaitpidZWNOHANGr#   ÚWORKER_BOOT_ERRORr   ÚAPP_LOAD_ERRORZWIFSIGNALEDr   r´   ZWTERMSIGr°   r`   r½   ri   r2   Z
child_exitr«   r¥   ZECHILD)r,   ZwpidÚstatusÚexitcoderx   rÂ   r¨   r   r   r   r   û  s6    



ý
zArbiter.reap_workersc                 C   s˜   t | jƒ| jk r|  ¡  | j ¡ }t|dd„ d}t |ƒ| jkr^| d¡\}}|  |tj	¡ q2t |ƒ}| j
|kr”|| _
| jjd |¡d|ddœd	 d
S )z[        Maintain the number of workers by spawning or killing
        as required.
        c                 S   s
   | d j S r:   )Zage)Úwr   r   r   r<   *  r=   z(Arbiter.manage_workers.<locals>.<lambda>r>   r   z{0} workerszgunicorn.workersZgauge)Zmetricr3   Úmtype)ÚextraN)rq   r°   rD   Úspawn_workersrK   rI   r`   rÀ   r   rž   r   r   rG   r8   )r,   rC   rZ   r   Zactive_worker_countr   r   r   r~   !  s     

þÿzArbiter.manage_workersc                 C   s4  |  j d7  _ |  | j | j| j| j| jd | j| j¡}| j | |¡ t	 
¡ }|dkrh||_|| j|< |S | j ¡ D ]}|j ¡  qrt	 ¡ |_zJzDt d| j ¡ | j d|j¡ | j | |¡ | ¡  t d¡ W n¬ tyè   ‚ Y nš tyD } zD| jjddd td	| tjd
 tj ¡  t | j¡ W Y d }~nFd }~0  ty€   | j  d¡ |j!srt | j"¡ t d¡ Y n0 W | j d|j¡ z|j ¡  | j #| |¡ W n& tyÖ   | j $dt% &¡ ¡ Y n0 nV| j d|j¡ z|j ¡  | j #| |¡ W n& ty,   | j $dt% &¡ ¡ Y n0 0 d S )Nr;   g       @r   zworker [%s]zBooting worker with pid: %sz'Exception while loading the applicationTrz   z%s)ÚfilezException in worker processr|   zWorker exiting (pid: %s)z Exception during worker exit:
%s)'r"   rA   rZ   r]   r-   rE   r2   r   Zpre_forkr   rµ   r°   Úvaluesr½   ri   rY   r   r}   rF   rV   Z	post_forkZinit_processr'   r‹   r‡   r   rG   ÚprintÚstderrÚflushrÆ   rˆ   Ú	exceptionZbootedrÅ   Úworker_exitr´   Ú	tracebackÚ
format_exc)r,   rÂ   rZ   Zsiblingr¨   r   r   r   r»   7  sd    þ

ÿ
 
ÿû
ÿ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)r_   rD   rq   r°   r»   r¯   r€   Úrandom)r,   r   r   r   r   rÌ   e  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,   ru   Zworker_pidsrZ   r   r   r   r™   q  s    zArbiter.kill_workersc                 C   s    zt  ||¡ W nŠ tyš } zr|jtjkr„z4| j |¡}|j ¡  | j	 
| |¡ W W Y d}~dS  ttfy‚   Y W Y d}~dS 0 ‚ W Y d}~n
d}~0 0 dS )zj        Kill a worker

        :attr pid: int, worker pid
        :attr sig: `signal.SIG*` value
         N)r   Úkillr«   r¥   ZESRCHr°   r`   r½   ri   r2   rÓ   rº   )r,   rZ   ru   r¨   rÂ   r   r   r   rÀ   z  s    
zArbiter.kill_worker)Nr   )T)2Ú__name__Ú
__module__Ú__qualname__Ú__doc__rÅ   rÆ   r+   r]   r°   rh   rr   ra   rk   ÚdictÚdirr   r‚   r.   r1   r5   ÚpropertyrD   r    rg   r\   rŽ   rl   r‘   r’   r”   r•   r—   r˜   rš   rœ   rŸ   r   rs   r†   r€   r‰   r›   r   r   r   r~   r»   rÌ   r™   rÀ   r   r   r   r   r
      s^   	ÿÿ
 1,

		


"7&.	r
   )r¥   r   rÖ   r©   r   r'   r¯   rÔ   Zgunicorn.errorsr   r   Zgunicorn.pidfiler   Zgunicornr   r   r   r   r	   Úobjectr
   r   r   r   r   Ú<module>   s   