
    AҐi                         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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      Zy)    N)
HaltServerAppImportError)Pidfile)socksystemdutil)__version__SERVER_SOFTWAREc                      e Zd ZdZdZdZi Zg Zi Ze	j                  Zdj                         D  cg c]  }t        t        d|z         c}}}} Z ed  ee	      D              Zd Zd Zd	 Z eee      Zd
 Zd Zd Zd Z	d Zd Zd ZeZd Zd Zd Z d Z!d Z"d Z#d Z$d Z%d Z&d Z'd Z(d2dZ)d3dZ*d4dZ+d  Z,d! Z-d" Z.d# Z/d$ Z0d% Z1d& Z2d' Z3d( Z4d) Z5d* Z6d+ Z7d, Z8d- Z9d. Z:d/ Z;d0 Z<d1 Z=yc c}}}} w )5Arbiterz
    Arbiter maintain the workers processes alive. It launches or
    kills them if needed. It also manages application reloading
    via SIGHUP/USR2.
          z+HUP QUIT INT TERM TTIN TTOU USR1 USR2 WINCHzSIG%sc              #      K   | ]7  }|d d dk(  r-|d   dk7  r%t        t        |      |dd  j                         f 9 y w)Nr   SIG_)getattrsignallower).0names     I/var/www/descvideos/venv/lib/python3.12/site-packages/gunicorn/arbiter.py	<genexpr>zArbiter.<genexpr>0   sI      6:8uaC 
	QR 01s   =?c                    t         t        j                  d<   d | _        d | _        d | _        t        j                         | _        | j                  |       d | _
        d| _        d| _        d| _        d| _        d| _        d| _        d | _        d | _        d | _        d dddd| _        t+        j,                         }t.        j0                  d d  }|j3                  dt.        j4                         ||t.        j4                  d| _        y )Nr
   Fr   Master)
start_timeworkers_spawnedworkers_killedreloads)argscwdr   )r
   osenviron_num_workers _last_logged_active_worker_countlogqueueSimpleQueue	SIG_QUEUEsetuppidfiler   
worker_age
reexec_pid
master_pidmaster_namedirty_arbiter_piddirty_arbiterdirty_pidfile_control_server_statsr   getcwdsysargvinsert
executable	START_CTX)selfappr    r   s       r   __init__zArbiter.__init__5   s    (7

$% 04- **,

3# "#!!  $  	
 kkmxx{As~~& ~~
    c                     | j                   S N)r#   r:   s    r   _get_num_workerszArbiter._get_num_workersd   s       r=   c                 d    | j                   }|| _         | j                  j                  | ||       y r?   )r#   cfgnworkers_changed)r:   value	old_values      r   _set_num_workerszArbiter._set_num_workersg   s+    %%	!!!$y9r=   c                    || _         |j                  | _        | j                  *| j                  j                  |j                        | _        dt        j
                  v r| j                  j                          | j                  j                  | _        | j                  j                  | _        | j                  j                  | _
        | j                  j                  | _        | j                  j                  | _        | j                  j                  dj                  dj                  d t!        | j                  j"                  j%                         d       D                           | j                  j&                  r?| j                  j&                  j%                         D ]  \  }}|t        j
                  |<    | j                  j(                  r| j                   j+                          y y )NGUNICORN_PIDzCurrent configuration:
{0}
c              3   Z   K   | ]#  \  }}d j                  ||j                         % yw)z
  {0}: {1}N)formatrE   )r   configrE   s      r   r   z Arbiter.setup.<locals>.<genexpr>   s-      ;!FE ##FEKK8;s   )+c                     | d   S N    )settings    r   <lambda>zArbiter.setup.<locals>.<lambda>   s
    gaj r=   key)r;   rC   r%   logger_classr!   r"   reopen_filesworker_classaddressworkersnum_workerstimeout	proc_namedebugrL   joinsortedsettingsitemsenvpreload_appwsgi)r:   r;   kvs       r   r)   zArbiter.setupm   sb   7788xx,,SWW5DH RZZ'HH!!# HH11xx''88++xx''++4;;II ; $((++1138:; ;< 	= 88<<**, "1 !

1" 88HHMMO  r=   c                    | j                   j                  dt               t        j                         | j                  d<   dt
        j                  v rHt        t
        j                  j                  d            | _	        | j                  dz   | _
        d| _        t        j                         | _        | j                  j                  _| j                  j                  }| j                  dk7  r|dz  }t!        |      | _        | j                  j#                  | j                         | j                  j%                  |        | j'                          | j(                  sd}t+        j,                         }|r3d| _        t/        t*        j0                  t*        j0                  |z         }n[| j                  rOg }t
        j                  j3                  d	      j5                  d
      D ]  }|j7                  t        |              | j                  j8                  rt;        t<        d      s0t?        j@                  | j                  | j                   |      | _        d
jC                  | j(                  D cg c]  }tE        |       c}      }| j                   jG                  d       | j                   j                  d|| j                         | j                   j                  d| j                  jH                         t+        jJ                  d| j                          t;        | jL                  d      r0| jL                  jO                  | j                  | j                          | j                  jP                  dkD  r&| j                  jR                  r| jU                          | jW                          | j                  jY                  |        yc c}w )zS        Initialize the arbiter. Start listening and set pidfile if needed.
        zStarting gunicorn %sr   rI   z.2zMaster.2Nr   TGUNICORN_FD,SO_REUSEPORTzArbiter bootedzListening at: %s (%s)zUsing worker: %sz&READY=1
STATUS=Gunicorn arbiter bootedcheck_config)-r%   infor	   timer3   r!   r"   intgetr-   r]   r.   getpidpidrC   r*   r   createon_startinginit_signals	LISTENERSr   
listen_fdsrangeSD_LISTEN_FDS_STARTpopsplitappend
reuse_porthasattrsocketr   create_socketsr_   strr^   worker_class_str	sd_notifyrX   rl   dirty_workers
dirty_appsspawn_dirty_arbiter_start_control_server
when_ready)r:   pidnamefdsrw   fdlnrlisteners_strs          r   startzArbiter.start   s    	,k: %)IIKL!RZZ'!"**.."@ADO!^^d2DN)D99;88'hh&&G!#4"7+DLLL)T"~~C ++-J#G77#77*DF **..7==cB (BJJs2w'( HH''GFN,K!%!4!4TXXtxx!Mdnn!Es#c(!EF'(-}dhhG($((*C*CDCTXXN 4$$n5**488TXX> 88!!A%$((*=*=$$& 	""$D!# "Fs   6Oc                     | j                   j                          | j                  D ]"  }t        j                  || j                         $ t        j                  t        j                  | j
                         y)z        Initialize master signal handling. Most of the signals
        are queued. Child signals only wake up the master.
        N)r%   close_on_execSIGNALSr   SIGCHLDsignal_chld)r:   ss     r   ru   zArbiter.init_signals   sS    
 	   	*AMM!T[[)	*fnnd&6&67r=   c                 :    | j                   j                  |       y)z3Signal handler - NO LOGGING, just queue the signal.Nr(   
put_nowaitr:   sigframes      r   r   zArbiter.signal       !!#&r=   c                 v   | j                          t        j                  d| j                  z         	 | j	                          	 | j                          | j                  d      D ]  }|| j                  vr| j                  j                  d|       .| j                  j                  |      }t        | d|z  d      }|s| j                  j                  d|       x|t        j                  k(  r| j                  j                  n| j                  j                  } |d	|        |         | j!                          | j	                          | j#                          # t$        t&        f$ r | j)                          Y yt*        $ r1}| j)                  |j,                  |j.                  
       Y d}~yd}~wt0        $ r  t2        $ rl | j                  j                  dd       | j5                  d       | j6                  | j6                  j9                          t;        j<                  d       Y yw xY w)zMain master loop.master [%s]T      ?)r\   zIgnoring unknown signal: %sz	handle_%sNzUnhandled signal: %szHandling signal: %s)reasonexit_statusz Unhandled exception in main loopexc_infoF)r   r   _setproctitler]   manage_workersmaybe_promote_masterwait_for_signals	SIG_NAMESr%   rm   rp   r   errorr   r   r^   murder_workersmanage_dirty_arbiterStopIterationKeyboardInterrupthaltr   r   r   
SystemExit	Exceptionstopr*   unlinkr5   exit)r:   r   signamehandler	log_levelinsts         r   runzArbiter.run   s   

=4>>9:%	!))+  000= C$..0&CSI "nn005G%dK',A4HG"'=wG 252GTXX]]I3W=I ##%##%))++ , 01 	IIK 	HIIT[[d6F6FIGG 	 	HHNN=$(  *IIe||'##%HHRL	s%   D.E" "H8H8'F77A>H87H8c                 :    | j                   j                  |       y)z;SIGCHLD signal handler - NO LOGGING, just queue the signal.Nr   r   s      r   r   zArbiter.signal_chld  r   r=   c                 D    | j                          | j                          y)z6SIGCHLD handling - called from main loop, safe to log.N)reap_workersreap_dirty_arbiterr@   s    r   handle_chldzArbiter.handle_chld	  s    !r=   c                     | j                   j                  d| j                         | j                          | j                  r | j                  t        j                         yy)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%   rm   r.   reloadr/   kill_dirty_arbiterr   SIGHUPr@   s    r   
handle_hupzArbiter.handle_hup  sE     	mT%5%56!!##FMM2 "r=   c                     t         )zSIGTERM handling)r   r@   s    r   handle_termzArbiter.handle_term  s    r=   c                 0    | j                  d       t        )zSIGINT handlingFr   r   r@   s    r   
handle_intzArbiter.handle_int#      		%r=   c                 0    | j                  d       t        )zSIGQUIT handlingFr   r@   s    r   handle_quitzArbiter.handle_quit(  r   r=   c                 N    | xj                   dz  c_         | j                          y)zR        SIGTTIN handling.
        Increases the number of workers by one.
        rP   Nr[   r   r@   s    r   handle_ttinzArbiter.handle_ttin-  s!    
 	Ar=   c                 n    | j                   dk  ry| xj                   dz  c_         | j                          y)zR        SIGTTOU handling.
        Decreases the number of workers by one.
        rP   Nr   r@   s    r   handle_ttouzArbiter.handle_ttou5  s2    
 q Ar=   c                     | j                   j                          | j                  t        j                         | j
                  r | j                  t        j                         yy)zU        SIGUSR1 handling.
        Kill all workers by sending them a SIGUSR1
        N)r%   rW   kill_workersr   SIGUSR1r/   r   r@   s    r   handle_usr1zArbiter.handle_usr1?  sF    
 	&..)!!##FNN3 "r=   c                 $    | j                          y)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)reexecr@   s    r   handle_usr2zArbiter.handle_usr2J  s     	r=   c                     | j                   j                  rB| j                  j                  d       d| _        | j                  t        j                         y| j                  j                  d       y)zSIGWINCH handlingzgraceful stop of workersr   z SIGWINCH ignored. Not daemonizedN)	rC   daemonr%   rm   r[   r   r   SIGTERMr^   r@   s    r   handle_winchzArbiter.handle_winchS  sI    88??HHMM45 Dfnn-HHNN=>r=   c                    | j                   dk(  ry | j                   t        j                         k7  r| j                  j	                  d       d| _        d| _         | j                  j                  | _        t        j                  d= | j                  /| j                  j                  | j                  j                         t        j                  d| j                  z         y y )Nr   zMaster has been promoted.r   rI   r   )r-   r!   getppidr%   rm   r.   rC   r]   r"   r*   renamer   r   r@   s    r   r   zArbiter.maybe_promote_master\  s    ??a??bjjl*HHMM56'DDO!XX//DN

>*||'##DHH$4$45}t~~=> +r=   c                 N    | j                   j                  | j                         y)z Wake up the arbiter's main loop.N)r(   r   WAKEUP_REQUESTr@   s    r   wakeupzArbiter.wakeupm  s    !!$"5"56r=   Nc                    | j                          | j                          |dk(  r| j                  j                  n| j                  j                  } |d| j
                         |	 |d|       | j                  | j                  j                          | j                  j                  |        t        j                  |       y)z halt arbiter r   zShutting down: %sNz
Reason: %s)_stop_control_serverr   r%   rm   r   r.   r*   r   rC   on_exitr5   r   )r:   r   r   log_funcs       r   r   zArbiter.haltq  s     	!!#		$/1$4488==$((..$d&6&67\6*<<#LL!r=   c                    g }	 | j                   j                  d|      }|| j                  k7  r|j                  |       	 	 | j                   j	                         }|| j                  k7  r|j                  |       <# t
        j                  $ r Y |S w xY w# t
        j                  $ r Y |S t        $ r t        j                          Y |S w xY w)ze        Wait for signals with timeout.
        Returns a list of signals that were received.
        T)blockr\   )
r(   rp   r   r|   
get_nowaitr&   Emptyr   r5   r   )r:   r\   signalsr   s       r   r   zArbiter.wait_for_signals  s    
 	..$$4$ACd)))s#..335Cd111s+	 
 {{ 
 {{ 	  ! 	HHJ	s;   >B :A> =B >BB BB C.CCc                    | j                   | j                  cxk(  xr dk(  nc xr& | j                   xr | j                  j                   }t        j                  | j                  |       g | _        t        j                  }|st        j                  }t        j                         | j                  j                  z   }| j                  r| j                  |       | j                  |       | }| j                   s| j                  r;t        j                         |k  r#|s	 | j"                  j%                         }|t        j&                  t        j                  fv r~| j(                  j+                  d       d}| j                  t        j                         | j                  r| j                  t        j                         t        j                         dz   }| j/                          | j1                          t        j2                  d       | j                   s| j                  rt        j                         |k  r#| j                  t        j4                         | j                  r| j                  t        j4                         | j/                          | j1                          y# t,        $ r Y w xY w)z        Stop workers

        :attr graceful: boolean, If True (the default) workers will be
        killed gracefully  (ie. trying to wait for the current connection)
        r   zQuick shutdown requestedT       @皙?N)r,   r-   r   rC   r}   r   close_socketsrv   r   r   SIGQUITrn   graceful_timeoutr/   r   r   WORKERSr(   r   SIGINTr%   rm   r   r   r   sleepSIGKILL)r:   gracefulr   r   limitquick_shutdownpending_sigs          r   r   zArbiter.stop  s    OOt3!3 (LL (HH''' 	
 	4>>62nn..C		dhh777 !!##C( 	#%||t55499;;N!"&..";";"=K"v}}fnn&EE&@A)-))&..911 33FNNC $		c 1 ##%JJsO# ||t55499;;N& 	&..)!!##FNN3! ! s   &B:J1 1	J=<J=c                 P   | j                   dk7  r| j                  j                  d       y| j                  dk7  r| j                  j                  d       yt	        j
                         }t	        j                         | _         | j                   dk7  ry| j                  j                  |        | j                  j                  j                         }t        |      |d<   | j                  rBt        t	        j
                               |d<   t        t        | j                              |d<   n%dj                  d	 | j                  D              |d
<   t	        j                   | j"                  d          t	        j$                  | j"                  d   | j"                  d   |       y)z1        Relaunch the master and workers.
        r   z"USR2 signal ignored. Child exists.Nz#USR2 signal ignored. Parent exists.rI   
LISTEN_PID
LISTEN_FDSrj   c              3   N   K   | ]  }t        |j                                 y wr?   )r   fileno)r   r   s     r   r   z!Arbiter.reexec.<locals>.<genexpr>  s       .=&)CJJL!.=s   #%ri   r    r   )r,   r%   warningr-   r!   rq   forkrC   pre_execenv_origcopyr   r   lenrv   r_   chdirr9   execvpe)r:   r-   r"   s      r   r   zArbiter.reexec  s:    ??aHHAB??aHHBCYY[
'')??a$((##((*"%j/<<$'		$4GL!$'DNN(;$<GL!%(XX .=-1^^.= &=GM" 	&' 	

4>>!$dnnV&<gFr=   c                    | j                   dxx   dz  cc<   | j                  j                  }| j                  j                  D ]W  }|| j                  j                  v r+| j                  j                  |   t
        j                  |<   F	 t
        j                  |= Y | j                  j                          | j                  | j                         | j                  j                          || j                  j                  k7  r| j                  D ]  }|j                           t        j                   | j                  | j                        | _        dj#                  | j                  D cg c]  }t%        |       c}      }| j                  j'                  d|       | j                  j)                  |        | j*                  | j*                  j-                          | j                  j*                  It/        | j                  j*                        | _        | j*                  j1                  | j2                         t5        j6                  d| j8                  z         | j:                  }t=        | j                  j>                        D ]  }| jA                           | jC                          tE        jF                         | j                  jH                  z   }tE        jF                         |k  r{| jJ                  sy tM        d | jJ                  jO                         D              }||kD  ry | jQ                          tE        jR                  d       tE        jF                         |k  rzy y # t        $ r Y <w xY wc c}w )Nr   rP   rj   zListening at: %sr   c              3   4   K   | ]  }|j                     y wr?   age)r   ws     r   r   z!Arbiter.reload.<locals>.<genexpr>6  s     >1>s   r   )*r3   rC   rY   rc   r   r!   r"   KeyErrorr;   r   r)   r%   rW   rv   closer   r   r_   r   rm   	on_reloadr*   r   r   rs   rr   r   r   r]   r+   rx   rZ   spawn_workerr   rn   	monotonicr   r   minvaluesr   r   )	r:   old_addressrf   r   r   last_worker_ager   deadlineoldests	            r   r   zArbiter.reload  s   I!#hh&&  
	ADHH%%% !% 1 1! 4

1

1
	 	

488 	 $((***~~ 		 "00488DDNHH$..%I3c#h%IJMHHMM,m< 	4  <<#LL! 88'"488#3#34DLLL) 	=4>>9: // txx''( 	 A	  	 >>#dhh&?&??nn)<<>(;(;(=>>F'JJsO nn)_   " &Js   M4/N4	N Nc                     | j                   syt        | j                  j                               }|D ]  \  }}	 t	        j
                         |j                  j                         z
  | j                   k  rD	 |j                  sD| j                  j                  d|       d|_
        | j                  |t        j                         | j                  |t        j                           y# t        t        f$ r Y w xY w)z)        Kill unused/idle workers
        NzWORKER TIMEOUT (pid:%s)T)r\   listr   rb   rn   r  tmplast_updateOSError
ValueErrorabortedr%   criticalkill_workerr   SIGABRTr   )r:   rZ   rr   workers       r   r   zArbiter.murder_workers<  s     ||t||))+,$ 	6MS&>>#fjj&<&<&>>$,,N O
 >>!!";SA!%  fnn5  fnn5	6 Z( s   <C++C=<C=c                    	 	 t        j                  dt         j                        \  }}|sy| j                  |k(  r	d| _        nd}t        j                  |      rt        j
                  |      }nt        j                  |      rt        j                  |      }	 t        j                  |      j                  }dj                  ||      }|t        j                  k(  r!|dz  }| j                  j                  |       nJ|t        j                   k(  r| j                  j#                  |       n| j                  j%                  |       |"|dk7  r| j                  j                  d||       || j&                  k(  rd}t)        || j&                        || j*                  k(  rd	}t)        || j*                        | j,                  j/                  |d      }|s|j0                  j3                          | j4                  j7                  | |       # t        $ r dj                  |      }Y ww xY w# t8        $ r(}	|	j:                  t:        j<                  k7  r Y d}	~	yd}	~	ww xY w)
z7        Reap workers to avoid zombie processes
        r   r   Nz	signal {}zWorker (pid:{}) was sent {}!z Perhaps out of memory?z$Worker (pid:%s) exited with code %s.zWorker failed to boot.zApp failed to load.)r!   waitpidWNOHANGr,   	WIFEXITEDWEXITSTATUSWIFSIGNALEDWTERMSIGr   Signalsr   r  rL   r   r%   r   r   rm   r   WORKER_BOOT_ERRORr   APP_LOAD_ERRORr   rz   r  r  rC   
child_exitr  errnoECHILD)
r:   wpidstatusexitcoder   sig_namemsgr   r  es
             r   r   zArbiter.reap_workersQ  s   4	!zz"bjj9f??d*&'DO
  $H||F+#%>>&#9/ kk&1?'-~~c':'?'?H =CC (, &..0#<<C HHNN3/ FNN2 HHMM#. !HH,,S1+A'M'+X7  4#9#99!9(1G1GHH4#6#66!6(1D1DEE!\\--dD9F! JJ$$&HH''f5a "  * ?'2'9'9#'>H?@  	ww%,,& '	sB   *H7 A/H7 H <EH7 H40H7 3H44H7 7	I( I##I(c                    t        | j                        | j                  k  r| j                          | j                  j	                         }t        |d       }t        |      | j                  kD  rM|j                  d      \  }}| j                  |t        j                         t        |      | j                  kD  rMt        |      }| j                  |k7  r7|| _
        | j                  j                  dj                  |      d|dd       | j                  j                  rSt!        d	 | j"                  D              }|dk\  r1| j                  j                  d
j                  |      d|dd       yyy)z[        Maintain the number of workers by spawning or killing
        as required.
        c                      | d   j                   S rO   r  )r	  s    r   rS   z(Arbiter.manage_workers.<locals>.<lambda>  s    ! r=   rT   r   z{0} workerszgunicorn.workersgauge)metricrE   mtype)extrac              3   F   K   | ]  } |j                          xs d   yw)r   N)get_backlog)r   r   s     r   r   z)Arbiter.manage_workers.<locals>.<genexpr>  s+      6" +$**,11 6s   !zsocket backlog: {0}zgunicorn.backlog	histogramN)r  r   r[   spawn_workersrb   r`   rz   r  r   r   r$   r%   r^   rL   rC   enable_backlog_metricsumrv   )r:   rZ   rr   r   active_worker_countbacklogs         r   r   zArbiter.manage_workers  sS   
 t||t/// ,,$$&&89'lT---{{1~HS!S&..1 'lT--- "'l004GG4GD1HHNN=//0CD,>+>+2"4  5
 88)) 6&*nn6 6G !|4;;GD0B/6/:&<  = 	 *r=   c           	         | xj                   dz  c_         | j                  | j                   | j                  | j                  | j                  | j
                  dz  | j                  | j                        }| j                  j                  | |       t        j                         }|dk7  r/||_        || j                  |<   | j                  dxx   dz  cc<   |S | j                  j                         D ]  }|j                  j                           t        j                          |_        	 t#        j$                  d| j&                  z         | j                  j)                  d|j                         | j                  j*                  r/t-        j.                  | j                  | j                        |_        | j                  j3                  | |       |j5                          t7        j8                  d       | j                  j)                  d|j                         	 |j                  j                          | j                  jQ                  | |       y # t:        $ r  t<        $ r}| j                  j?                  dd	       tA        d
|z  t6        jB                         t6        jB                  jE                          t7        j8                  | jF                         Y d }~d }~wtH        $ r}| j                  jK                  d       tA        d
|z  t6        jB                         t6        jB                  jE                          |jL                  st7        j8                  | jN                         t7        j8                  d       Y d }~d }~ww xY w# tH        $ r1 | j                  jS                  dtU        jV                                Y y w xY w# | j                  j)                  d|j                         	 |j                  j                          | j                  jQ                  | |       w # tH        $ r1 | j                  jS                  dtU        jV                                Y w w xY wxY w)NrP   r   r   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+   rX   rr   rv   r;   r\   rC   r%   pre_forkr!   r   r   r3   r  r  r  rq   r   r   r]   rm   r}   r   r   sockets	post_forkinit_processr5   r   r   r   r^   printstderrflushr)  r   	exceptionbootedr(  worker_exitr   	traceback
format_exc)r:   r  rr   siblingr2  s        r   r  zArbiter.spawn_worker  s$   1""4??DHHdnn#'88T\\C-?#'88TXX7 	$'ggi!8FJ &DLLKK)*a/*J ||**, 	 GKK	  YY[
	9}t~~=>HHMM7Dxx""!%!4!4TXXtxx!HHHtV,!HHQK" HHMM4fjjA9

  "$$T62'  	 	*HHNND$(  *$(,JJHHT(()) 	HH<=$(,JJ==//0HHRLL	  9  !D!*!5!5!799	 HHMM4fjjA9

  "$$T62 9  !D!*!5!5!799su   -CI "6N N+A8K(#O (N4BNO NO 7OO'Q2>6P54Q257Q/,Q2.Q//Q2c                     t        | j                  t        | j                        z
        D ]<  }| j	                          t        j                  dt        j                         z         > y)z        Spawn new workers as needed.

        This is where a worker process leaves the main loop
        of the master process.
        r   N)rx   r[   r  r   r  rn   r   random)r:   r   s     r   r<  zArbiter.spawn_workers  sO     t''#dll*;;< 	.AJJsV]]_,-	.r=   c                 |    t        | j                  j                               }|D ]  }| j                  ||        y)z^        Kill all workers with the signal `sig`
        :attr sig: `signal.SIG*` value
        N)r  r   keysr  )r:   r   worker_pidsrr   s       r   r   zArbiter.kill_workers  s:    
 4<<,,./ 	'CS#&	'r=   c                    	 t        j                  ||       |t        j                  t        j                  fv r| j
                  dxx   dz  cc<   yy# t        $ r}|j                  t        j                  k(  rp	 | j                  j                  |      }|j                  j                          | j                  j                  | |       Y d}~y# t        t        f$ r Y Y d}~yw xY w d}~ww xY w)zj        Kill a worker

        :attr pid: int, worker pid
        :attr sig: `signal.SIG*` value
         r   rP   N)r!   killr   r   r   r3   r  r+  ESRCHr   rz   r  r  rC   rL  r
  )r:   rr   r   r2  r  s        r   r  zArbiter.kill_worker  s    	GGCv~~v~~66,-2- 7 		ww%++%!\\--c2FJJ$$&HH((v6 '* 		s7   AA 	C/C*:ACC&C*%C&&C**C/c                     ddl }| j                  j                  dd      j                  dd      }t        j                  j                  |j                         d| d      S )a)  Get the well-known PID file path for orphan detection.

        Uses self.proc_name (not self.cfg.proc_name) so that during USR2
        the new master gets a different PID file path ("myapp.2" vs "myapp").
        This prevents the old dirty arbiter from removing the new one's PID file.
        r   N/r    zgunicorn-dirty-z.pid)tempfiler]   replacer!   pathr_   
gettempdir)r:   r[  	safe_names      r   _get_dirty_pidfile_pathzArbiter._get_dirty_pidfile_path  sQ     	NN**34<<S#F	ww||H//1_YKt3TUUr=   c                    | j                   dk7  ry| j                         }t        j                  j	                  |      sy	 t        |      5 }t        |j                         j                               }ddd       t        j                  d       | j                  j                  d|       t        j                  |t        j                         t        d      D ].  }t        j                   d       	 t        j                  |d       0 t        j                  |t        j$                         	 t        j*                  |       y# 1 sw Y   xY w# t"        $ r Y  /w xY w# t&        t(        t"        f$ r Y Iw xY w# t"        $ r Y yw xY w)zKill any orphaned dirty arbiter from a previous crash.

        Only runs on fresh start (master_pid == 0), not during USR2.
        r   Nz(Killing orphaned dirty arbiter (pid: %s)
   r   )r-   r`  r!   r]  existsopenro   readstriprV  r%   r   r   r   rx   rn   r   r  r   r  IOErrorr   )r:   r*   fold_pidr   s        r   _cleanup_orphaned_dirty_arbiterz'Arbiter._cleanup_orphaned_dirty_arbiter  s;    ??a..0ww~~g&	g 0!affhnn./0 GGGQHHGQGGGV^^,2Y 1

3GGGQ'1 0
	IIg-0 0   GW- 		  		sa   E& (E
5BE& 7E&E& 4F  
EE& 	E#E& "E##E& &E=<E= 	FFc                    ddl m}m} | j                  ry| j	                          | j                         | _         || j                  | j                  | j                        | _	        | j                  j                  }t        j                         }|dk7  rA|| _         ||       |t        j                  d<   | j                  j                  d||       |S 	 | j                  j                          t!        j"                  d       y# t$        $ r  t&        $ r3 | j                  j)                  d       t!        j"                  d       Y yw xY w)	z        Spawn the dirty arbiter process.

        The dirty arbiter manages a separate pool of workers for
        long-running, blocking operations.
        r   )DirtyArbiterset_dirty_socket_pathN)r*   GUNICORN_DIRTY_SOCKETz%Spawned dirty arbiter (pid: %s) at %sz"Exception in dirty arbiter processr   )gunicorn.dirtyrl  rm  r/   rj  r`  r1   rC   r%   r0   socket_pathr!   r   r"   rm   r   r5   r   r   r   rJ  )r:   rl  rm  rp  rr   s        r   r   zArbiter.spawn_dirty_arbiterA  s    	G!! 	,,. "99;)HHdhh&&
 ((44ggi!8%(D"!+.2=BJJ./HHMMA{,J	""$HHQK 	 	HHCDHHRL	s   /D
 
AEEc                     | j                   sy	 t        j                  | j                   |       y# t        $ r:}|j                  t        j
                  k(  rd| _         d| _        Y d}~yY d}~yd}~ww xY w)z\        Send a signal to the dirty arbiter.

        :attr sig: `signal.SIG*` value
        Nr   )r/   r!   rV  r  r+  rW  r0   )r:   r   r2  s      r   r   zArbiter.kill_dirty_arbitero  sa     %%	*GGD**C0 	*ww%++%)*&%)"" &	*s    0 	A3+A..A3c                    | j                   sy	 t        j                  | j                   t        j                        \  }}|syt        j                  |      rUt        j
                  |      }|dk7  r| j                  j                  d||       nd| j                  j                  d|       nGt        j                  |      r2t        j                  |      }| j                  j                  d||       d| _         d| _        y# t        $ r:}|j                  t        j                  k(  rd| _         d| _        Y d}~yY d}~yd}~ww xY w)zA        Reap the dirty arbiter process if it has exited.
        Nr   z*Dirty arbiter (pid:%s) exited with code %szDirty arbiter (pid:%s) exitedz*Dirty arbiter (pid:%s) killed by signal %s)r/   r!   r!  r"  r#  r$  r%   r   rm   r%  r&  r   r0   r  r+  r,  )r:   r-  r.  r/  r   r2  s         r   r   zArbiter.reap_dirty_arbiter  s    %%	*::d&<&<bjjILD&||F#>>&1q=HHNN#O#'3 HHMM"A4H'kk&)  !M!%s, &'D"!%D 	*ww%,,&)*&%)"" '	*s   3D B?D 	E+EEc                     | j                   ry| j                  j                  dkD  rC| j                  j                  r,| j                  j                  d       | j                          yyy)zL        Maintain the dirty arbiter process by respawning if needed.
        Nr   zSpawning dirty arbiter...)r/   rC   r   r   r%   rm   r   r@   s    r   r   zArbiter.manage_dirty_arbiter  sS     !!88!!A%$((*=*=HHMM56$$& +>%r=   c                     | j                   j                  }t        j                  j	                  |      s2t        j                  j                  t        j                         |      }|S )z<Get the control socket path, making relative paths absolute.)rC   control_socketr!   r]  isabsr_   r   r4   )r:   rp  s     r   _get_control_socket_pathz Arbiter._get_control_socket_path  sA    hh--ww}}[)'',,t{{}kBKr=   c                    | j                   j                  r| j                  j                  d       yddlm} | j                         }| j                   j                  }	  || ||      | _        | j                  j                          y# t        $ r-}| j                  j                  d|       d| _        Y d}~yd}~ww xY w)z        Start the control socket server.

        The server runs in a background thread and accepts commands
        via Unix socket.
        zControl socket disabledNr   )ControlSocketServerz"Failed to start control socket: %s)rC   control_socket_disabler%   r^   gunicorn.ctl.serverry  rw  control_socket_moder2   r   r   r   )r:   ry  rp  socket_moder2  s        r   r   zArbiter._start_control_server  s     88**HHNN45 	<335hh22	(#6k;$D    &&( 	(HHA1E#'D  	(s    )B
 
	C #B;;C c                     | j                   r#	 | j                   j                          d| _         yy# t        $ r&}| j                  j	                  d|       Y d}~3d}~ww xY w)z0        Stop the control socket server.
        z!Error stopping control server: %sN)r2   r   r   r%   r^   )r:   r2  s     r   r   zArbiter._stop_control_server  s^     G$$))+ $(D     GBAFFGs   1 	A AA )Nr   )r   )T)>__name__
__module____qualname____doc__r(  r)  r9   rv   r   r   NSIGr   r{   r   r   dictdirr   r<   rA   rG   propertyr[   r)   r   ru   r   r   r   
handle_cldr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r<  r   r  r`  rj  r   r   r   r   rw  r   r   )r   xr   r   s   0000r   r   r      s     NIIG [[N FKKMO O vw{+ OG >A&k I
-
^!: +-=>K@:"x
8'*X'" J3

	4??"7"24"l GDGR6*8t=@19f
.'6	V&P,\* *>	'(4	(AOs   C4
r   )r+  r!   r&   rQ  r   r5   rn   rM  r   gunicorn.errorsr   r   gunicorn.pidfiler   gunicornr   r   r   r	   r
   r   rQ   r=   r   <module>r     s=     	    
    6 $ ( ( 1
@( @(r=   