o
    Æ[hÞ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   úw/home/ubuntu/experiments/live_experiments/Pythonexperiments/Otree/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   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__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 r/   )r   ÚcfgZ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)Úformatr3   )r   Úconfigr3   r   r   r   r   i   s
   € ÿ
ÿz Arbiter.setup.<locals>.<genexpr>c                 S   s   | d S ©Né   r   )Zsettingr   r   r   Ú<lambda>m   s    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    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 %sr6   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$   rE   r%   ÚgetpidÚpidr2   r!   r   ÚcreateZon_startingÚinit_signalsÚ	LISTENERSr   Ú
listen_fdsÚrangeZSD_LISTEN_FDS_STARTÚpopÚsplitÚappendr   Úcreate_socketsrG   rF   Zworker_class_strZ	sd_notifyÚhasattrr@   rV   Z
when_ready)r,   ZpidnameÚfdsr_   Ú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   Zset_non_blockingZclose_on_execr   ÚSIGNALSr   Ú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 d S )Né   )ÚlenÚ	SIG_QUEUErc   Ú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éÿÿÿÿ)ri   r   Ú_setproctitlerE   Úmanage_workersÚmaybe_promote_masterru   ra   ÚsleepÚmurder_workersÚ	SIG_NAMESr   rW   rY   r   Úerrorrv   ÚStopIterationÚKeyboardInterruptÚhaltr   r{   r|   Ú
SystemExitÚ	ExceptionÚstopr!   Úunlinkr'   Úexit)r,   rx   ÚsignameÚhandlerÚinstr   r   r   ÚrunÃ   sP   
ë €ÿ


úzArbiter.runc                 C   s   |   ¡  |  ¡  dS )zSIGCHLD handlingN)Úreap_workersrv   rw   r   r   r   ro   ï   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   rW   r%   Úreloadr0   r   r   r   Ú
handle_hupô   s   zArbiter.handle_hupc                 C   s   t ‚)zSIGTERM handling)r‡   r0   r   r   r   Úhandle_termþ   s   zArbiter.handle_termc                 C   ó   |   d¡ t‚)zSIGINT handlingF©rŒ   r‡   r0   r   r   r   Ú
handle_int  ó   
zArbiter.handle_intc                 C   r—   )zSIGQUIT handlingFr˜   r0   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©rC   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   Ú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   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)	r2   Údaemonr   rW   rC   rŸ   r   ÚSIGTERMrF   r0   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   r6   rz   )r$   r   Úgetppidr   rW   r%   r2   rE   r   r!   Úrenamer   r€   r0   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   Úwriterj   ÚOSErrorÚerrnoÚEAGAINÚEINTR)r,   Úer   r   r   rv   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   rW   r†   r%   r!   r   r2   Zon_exitr'   rŽ   )r,   r{   r|   Z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¬   )Úselectrj   r   Úreadr«   r   r   r¬   r­   r®   rˆ   r'   rŽ   )r,   Úreadyr¯   Z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   r2   Ú
reuse_portr   Zclose_socketsr^   r   r¥   ÚSIGQUITÚtimeZgraceful_timeoutrŸ   ÚWORKERSrƒ   ÚSIGKILL)r,   Zgracefulr   rx   Ú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.r6   Z
LISTEN_PIDZ
LISTEN_FDSrO   c                 s   s    | ]	}t | ¡ ƒV  qd S r/   )rR   ÚfilenorS   r   r   r   r   ©  s   € 
ÿz!Arbiter.reexec.<locals>.<genexpr>rN   r   r   )r#   r   Úwarningr$   r   rZ   Úforkr2   Zpre_execÚenv_origÚcopyrR   r   rt   r^   rG   Ú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 )NrO   c                 S   rP   r   rQ   rS   r   r   r   r   Ï  rU   z"Arbiter.reload.<locals>.<listcomp>zListening at: %srz   )r2   rA   rK   r½   r   r   ÚKeyErrorr-   r”   r    r   r?   r^   rk   r   rd   rG   rW   Z	on_reloadr!   r   r   r\   r[   r   r€   rE   r`   rB   Úspawn_workerr   )r,   Zold_addressrL   rT   rh   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)rD   Úlistr·   rJ   r¶   Ú	monotonicÚtmpZlast_updater«   Ú
ValueErrorZabortedr   ÚcriticalÚkill_workerr   ÚSIGABRTr¸   )r,   rB   r[   Ú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Æ   r8   r¸   r·   ra   rÅ   rk   r2   Z
child_exitr«   r¬   ZECHILD)	r,   ÚwpidÚstatusÚexitcoder{   Z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:   )Zage)Úwr   r   r   r<   =  s   
 z(Arbiter.manage_workers.<locals>.<lambda>r=   r   z{0} workerszgunicorn.workersZgauge)Zmetricr3   Úmtype)ÚextraN)rt   r·   rC   Úspawn_workersrJ   rH   ra   rÈ   r   r¥   r   r   rF   r8   )r,   rB   r[   r   Z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"   r@   r[   r^   r-   rD   r2   r   Zpre_forkr   r¼   r·   ÚvaluesrÅ   rk   rZ   r   r€   rE   rW   Z	post_forkZinit_processr'   rŽ   rŠ   r   rF   ÚprintÚstderrÚflushrÏ   r‹   Ú	exceptionZbootedrÎ   Úworker_exitr»   Ú	tracebackÚ
format_exc)r,   rÊ   r[   Z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)r`   rC   rt   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,   rx   Zworker_pidsr[   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¬   ZESRCHr·   ra   rÅ   rk   r2   rß   rÁ   )r,   r[   rx   r¯   rÊ   r   r   r   rÈ     s   
ÿ€÷zArbiter.kill_worker)Nr   )T)2Ú__name__Ú
__module__Ú__qualname__Ú__doc__rÎ   rÏ   r+   r^   r·   rj   ru   rb   rm   ÚdictÚdirr   r…   r.   r1   r5   ÚpropertyrC   r    ri   r]   r’   ro   r•   r–   r™   r›   r   rž   r¡   r£   r¦   r‚   rv   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à   Zgunicorn.errorsr   r   Zgunicorn.pidfiler   Zgunicornr   r   r   r   r	   r
   r   r   r   r   Ú<module>   s   