o
    ƒ¡gÞ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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ƒ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   úe/var/www/primordialfields.com/dashboard_backend/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__2   s$   

ýzArbiter.__init__c                 C   s   | j S ©N)r   ©r-   r   r   r   Ú_get_num_workersN   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_workersQ   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_PIDzCurrent configuration:
{0}Ú
c                 s   s"    | ]\}}d   ||j¡V  qdS )z
  {0}: {1}N)Úformatr5   )r   Úconfigr5   r   r   r   r   i   s
   € ÿ
ÿz Arbiter.setup.<locals>.<genexpr>c                 S   s   | d S ©Né   r   )Úsettingr   r   r   Ú<lambda>m   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!   W   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s†d}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 %sr8   z.2zMaster.2Nr   TÚGUNICORN_FDú,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   Ústartw   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_winch/  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   r8   rˆ   )r%   r   Úgetppidr    r]   r&   r3   rI   r   r"   Úrenamer   rŽ   r1   r   r   r   r   8  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   ÚOSErrorÚerrnoÚEAGAINÚEINTR)r-   Úer   r   r   r„   I  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—   S  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yQ } zt|d|jd ƒ}|tjtj	fvrF‚ W Y d}~dS d}~w t
y^   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¹   r   r   rº   r»   r¼   r–   r(   rœ   )r-   Úreadyr½   Úerror_numberr   r   r   r‘   a  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š   t  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.r8   Ú
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>rT   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r‰t| 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r€zt	 
|¡j}W n tyj   d	 |¡}Y nw d
 ||¡}|t	jkrz|d7 }| j |¡ | j |d¡}|sŠq|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   4  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	 ¡ |_z z"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!s³t | 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Ú   J  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ù   x  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	   r
   r   r   r   r   Ú<module>   s   