
y XK                 @   s   d  d l  m 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 d  d l m Z d  d l m Z m Z Gd d	   d	 e  Z d S)
    )print_functionN)
HaltServerAppImportError)Pidfile)create_sockets)util)__version__SERVER_SOFTWAREc               @   s  e  Z d  Z d Z d Z d Z i  Z g  Z i  Z g  Z	 g  Z
 d d   d j   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% d1 d2 d3 d4  Z& d5 d6   Z' d7 d8 d9  Z( d: d;   Z) d< d=   Z* d> d?   Z+ d@ dA   Z, dB dC   Z- dD dE   Z. dF dG   Z/ dH dI   Z0 dJ dK   Z1 d1 S)L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   @/home/ubuntu/projects/ifolica/build/gunicorn/gunicorn/arbiter.py
<listcomp>/   s   	zArbiter.<listcomp>z+HUP QUIT INT TERM TTIN TTOU USR1 USR2 WINCHc             c   sZ   |  ]P } | d  d  d k r | d d k r t  t |  | d d   j   f Vq d  S)Nr   ZSIG_)r   r   lower)r   namer   r   r   	<genexpr>2   s    zArbiter.<genexpr>c             C   s   t  t j d <d  |  _ d  |  _ d  |  _ |  j |  d  |  _ d |  _ d |  _	 d |  _
 d |  _ t j   } t j d  d   } | j d t j  i | d 6| d 6t j d 6|  _ d  S)Nr	   r   Masterargscwd)r	   osenviron_num_workers _last_logged_active_worker_countlogsetuppidfile
worker_age
reexec_pid
master_pidmaster_namer   getcwdsysargvinsert
executable	START_CTX)selfappr   r   r   r   r   __init__6   s"    								zArbiter.__init__c             C   s   |  j  S)N)r   )r,   r   r   r   _get_num_workersQ   s    zArbiter._get_num_workersc             C   s,   |  j  } | |  _  |  j j |  | |  d  S)N)r   cfgZnworkers_changed)r,   value	old_valuer   r   r   _set_num_workersT   s    		zArbiter._set_num_workersc          	   C   sU  | |  _  | j |  _ |  j d  k r? |  j j | j  |  _ n  d t j k r^ |  j j   n  |  j j |  _ |  j j |  _ |  j j	 |  _
 |  j j |  _ |  j j |  _ |  j j d j d j d d   t |  j j j   d d d   D    |  j j r5x0 |  j j j   D] \ } } | t j | <qWn  |  j j rQ|  j  j   n  d  S)	NGUNICORN_FDzCurrent configuration:
{0}
c             s   s*   |  ]  \ } } d  j  | | j  Vq d S)z
  {0}: {1}N)formatr1   )r   configr1   r   r   r   r   m   s   z Arbiter.setup.<locals>.<genexpr>keyc             S   s   |  d S)N   r   )Zsettingr   r   r   <lambda>p   s    zArbiter.setup.<locals>.<lambda>)r-   r0   r   Zlogger_classr   r   reopen_filesworker_classaddressworkersnum_workerstimeout	proc_namedebugr6   joinsortedZsettingsitemsenvZpreload_appZwsgi)r,   r-   kvr   r   r   r    Z   s*    		zArbiter.setupc             C   s  |  j  j d t  d t j k rY t t j j d   |  _ |  j d |  _ d |  _	 n  t j
   |  _ |  j j d k	 r |  j j } |  j d k r | d 7} n  t |  |  _ |  j j |  j  n  |  j j |   |  j   |  j st |  j |  j   |  _ n  d j d d	   |  j D  } |  j  j d
  |  j  j d | |  j  |  j  j d |  j j  t |  j d  r|  j j |  j |  j   n  |  j j |   d S)zS        Initialize the arbiter. Start listening and set pidfile if needed.
        zStarting gunicorn %sGUNICORN_PIDz.2zMaster.2Nr   ,c             S   s   g  |  ] } t  |   q Sr   )str)r   lr   r   r   r      s   	 z!Arbiter.start.<locals>.<listcomp>zArbiter bootedzListening at: %s (%s)zUsing worker: %scheck_config)r   infor   r   r   intgetr$   rA   r%   getpidpidr0   r!   r   createZon_startinginit_signals	LISTENERSr   rC   rB   Zworker_class_strhasattrr<   rM   Z
when_ready)r,   Zpidnamelisteners_strr   r   r   startz   s.    
	zArbiter.startc                s     j  r  d d     j  D n  t j     _  } x( | D]  } t j |  t j |  q: W  j j     f d d     j D t j t j	   j
  d S)z        Initialize master signal handling. Most of the signals
        are queued. Child signals only wake up the master.
        c             S   s   g  |  ] } t  j |   q Sr   )r   close)r   pr   r   r   r      s   	 z(Arbiter.init_signals.<locals>.<listcomp>c                s%   g  |  ] } t  j  |   j    q Sr   )r   )r   s)r,   r   r   r      s   	 N)PIPEr   piper   Zset_non_blockingZclose_on_execr   SIGNALSr   SIGCHLDhandle_chld)r,   pairrZ   r   )r,   r   rT      s    	zArbiter.init_signalsc             C   s6   t  |  j  d k  r2 |  j j |  |  j   n  d  S)N   )len	SIG_QUEUEappendwakeup)r,   sigframer   r   r   r      s    zArbiter.signalc             C   s  |  j    t j d |  j  y	|  j   x |  j   t |  j  rY |  j j d  n d } | d k r |  j	   |  j
   |  j   q. n  | |  j k r |  j j d |  q. n  |  j j |  } t |  d | d  } | s |  j j d |  q. n  |  j j d |  |   |  j   q. WWn t k
 rE|  j   Yn t k
 r`|  j   Yn t k
 r} z! |  j d | j d	 | j  WYd d } ~ Xnu t k
 r  Yna t k
 r|  j j d
 d d |  j d  |  j d k	 r|  j j   n  t j d  Yn Xd S)zMain master loop.zmaster [%s]r   NzIgnoring unknown signal: %sz	handle_%szUnhandled signal: %szHandling signal: %sreasonexit_statusz Unhandled exception in main loopexc_infoTFr9   )rX   r   _setproctitlerA   manage_workersmaybe_promote_masterrc   rd   popsleepmurder_workers	SIG_NAMESr   rN   rP   r   errorrf   StopIterationhaltKeyboardInterruptr   ri   rj   
SystemExit	Exceptionstopr!   unlinkr'   exit)r,   rg   Zsignamehandlerinstr   r   r   run   sL    


'


.zArbiter.runc             C   s   |  j    |  j   d S)zSIGCHLD handlingN)reap_workersrf   )r,   rg   rh   r   r   r   r`      s    
zArbiter.handle_chldc             C   s$   |  j  j d |  j  |  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   rN   r%   reload)r,   r   r   r   
handle_hup   s    zArbiter.handle_hupc             C   s
   t   d S)zSIGTERM handlingN)ru   )r,   r   r   r   handle_term   s    zArbiter.handle_termc             C   s   |  j  d  t  d S)zSIGINT handlingFN)rz   ru   )r,   r   r   r   
handle_int   s    zArbiter.handle_intc             C   s   |  j  d  t  d S)zSIGQUIT handlingFN)rz   ru   )r,   r   r   r   handle_quit   s    zArbiter.handle_quitc             C   s   |  j  d 7_  |  j   d S)zR        SIGTTIN handling.
        Increases the number of workers by one.
        r9   N)r?   rn   )r,   r   r   r   handle_ttin  s    zArbiter.handle_ttinc             C   s0   |  j  d k r d S|  j  d 8_  |  j   d S)zR        SIGTTOU handling.
        Decreases the number of workers by one.
        r9   N)r?   rn   )r,   r   r   r   handle_ttou
  s    zArbiter.handle_ttouc             C   s!   |  j  j   |  j t j  d S)zU        SIGUSR1 handling.
        Kill all workers by sending them a SIGUSR1
        N)r   r;   kill_workersr   SIGUSR1)r,   r   r   r   handle_usr1  s    zArbiter.handle_usr1c             C   s   |  j    d S)z        SIGUSR2 handling.
        Creates a new master/worker set as a slave of the current
        master without affecting old workers. Use this to do live
        deployment with the ability to backout a change.
        N)reexec)r,   r   r   r   handle_usr2  s    zArbiter.handle_usr2c             C   sL   |  j  j r8 |  j j d  d |  _ |  j t j  n |  j j d  d S)zSIGWINCH handlingzgraceful stop of workersr   z SIGWINCH ignored. Not daemonizedN)	r0   daemonr   rN   r?   r   r   SIGTERMrB   )r,   r   r   r   handle_winch%  s
    	zArbiter.handle_winchc             C   s   |  j  d k r d  S|  j  t j   k r |  j j d  d |  _ d |  _  |  j j |  _ t j d =|  j	 d  k	 r |  j	 j
 |  j j	  n  t j d |  j  n  d  S)Nr   zMaster has been promoted.r   rI   zmaster [%s])r$   r   getppidr   rN   r%   r0   rA   r   r!   renamer   rm   )r,   r   r   r   ro   .  s    		
zArbiter.maybe_promote_masterc             C   sh   y t  j |  j d d  WnF t k
 rc } z& | j t j t j g k rQ   n  WYd d } ~ Xn Xd S)z;        Wake up the arbiter by writing to the PIPE
        r9      .N)r   writer\   IOErrorerrnoEAGAINEINTR)r,   er   r   r   rf   ?  s
    zArbiter.wakeupNr   c             C   s   |  j    |  j j d |  j  | d k	 rB |  j j d |  n  |  j d k	 ra |  j j   n  |  j j |   t j	 |  d S)z halt arbiter zShutting down: %sNz
Reason: %s)
rz   r   rN   r%   r!   r{   r0   Zon_exitr'   r|   )r,   ri   rj   r   r   r   rv   I  s    
zArbiter.haltc             C   s  yT t  j  |  j d g g  g  d  } | d s3 d Sx t j |  j d d  rR q6 WWn t  j k
 r } z* | j d t j t j g k r   n  WYd d } ~ Xna t	 k
 r } z& | j t j t j g k r   n  WYd d } ~ Xn t
 k
 rt j   Yn Xd S)zm        Sleep until PIPE is readable or we timeout.
        A readable PIPE means a signal occurred.
        r   g      ?Nr9   )selectr\   r   readrt   r   r   r   r   OSErrorrw   r'   r|   )r,   readyr   r   r   r   rq   T  s    "
zArbiter.sleepTc             C   s   |  j  d k r? |  j d k r? x |  j D] } | j   q( Wn  g  |  _ t j } | sc t j } n  t j   |  j j	 } |  j
 |  x, |  j r t j   | k  r t j d  q W|  j
 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   g?N)r#   r$   rU   rY   r   r   SIGQUITtimer0   Zgraceful_timeoutr   WORKERSrq   SIGKILL)r,   ZgracefulrL   rg   limitr   r   r   rz   h  s    		zArbiter.stopc             C   s  |  j  d k r# |  j j d  d S|  j d k rF |  j j d  d St j   } t j   |  _  |  j  d k rt d S|  j j |   |  j j	 j
   } d d   |  j D } d j d d   | D  | d	 <t |  | d
 <t j |  j d  t j |  j d |  j d |  d S)z1        Relaunch the master and workers.
        r   z"USR2 signal ignored. Child exists.Nz"USR2 signal ignored. Parent existsc             S   s   g  |  ] } | j     q Sr   )fileno)r   rL   r   r   r   r     s   	 z"Arbiter.reexec.<locals>.<listcomp>rJ   c             S   s   g  |  ] } t  |   q Sr   )rK   )r   fdr   r   r   r     s   	 r4   rI   r   r   )r#   r   warningr$   r   rQ   forkr0   Zpre_execenv_origcopyrU   rC   rK   chdirr+   execvpe)r,   r$   r   Zfdsr   r   r   r     s"     zArbiter.reexecc             C   s  |  j  j } xc |  j  j D]U } | |  j  j k rK |  j  j | t j | <q y t j | =Wq t k
 rm Yq Xq W|  j j   |  j	 |  j  |  j
 j   | |  j  j k rd d   |  j D t |  j  |  j
  |  _ d j d d   |  j D  } |  j
 j d |  n  |  j  j |   |  j d  k	 r>|  j j   n  |  j  j d  k	 r{t |  j  j  |  _ |  j j |  j  n  t j d |  j  x$ t |  j  j  D] } |  j   qW|  j   d  S)Nc             S   s   g  |  ] } | j     q Sr   )rY   )r   rL   r   r   r   r     s   	 z"Arbiter.reload.<locals>.<listcomp>rJ   c             S   s   g  |  ] } t  |   q Sr   )rK   )r   rL   r   r   r   r     s   	 zListening at: %szmaster [%s])r0   r=   rF   r   r   r   KeyErrorr-   r   r    r   r;   rU   r   rC   rN   Z	on_reloadr!   r{   r   rS   rR   r   rm   rA   ranger>   spawn_workerrn   )r,   Zold_addressrG   rW   ir   r   r   r     s4    	zArbiter.reloadc             C   s   |  j  s d St |  j j    } x | D] \ } } y, t j   | j j   |  j  k r` w) n  Wn t t f k
 r~ w) Yn X| j	 s |  j
 j d |  d | _	 |  j | t j  q) |  j | t j  q) Wd S)z)        Kill unused/idle workers
        NzWORKER TIMEOUT (pid:%s)T)r@   listr   rE   r   tmpZlast_updater   
ValueErrorZabortedr   criticalkill_workerr   SIGABRTr   )r,   r>   rR   workerr   r   r   rr     s    	"
		zArbiter.murder_workersc             C   s  y x t  j d t  j  \ } } | s+ Pn  |  j | k rF d |  _ q | d ?} | |  j k rz d } t | |  j   n  | |  j k r d } t | |  j   n  |  j j | d  } | s q n  | j	 j
   q WWn= t k
 r} z | j t j k r  n  WYd d } ~ Xn Xd S)z7        Reap workers to avoid zombie processes
        r9   r      zWorker failed to boot.zApp failed to load.Nrl   )r   waitpidWNOHANGr#   WORKER_BOOT_ERRORr   APP_LOAD_ERRORr   rp   r   rY   r   r   ECHILD)r,   wpidstatusZexitcoderi   r   r   r   r   r   r     s*    
zArbiter.reap_workersc             C   s   t  |  j j    |  j k  r+ |  j   n  |  j j   } t | d d d   } xA t  |  |  j k r | j d  \ } } |  j | t	 j
  qU Wt  |  } |  j | k r | |  _ |  j j d j |  d i d d 6| d	 6d
 d 6n  d S)z[        Maintain the number of workers by spawning or killing
        as required.
        r8   c             S   s   |  d j  S)Nr9   )Zage)wr   r   r   r:     s    z(Arbiter.manage_workers.<locals>.<lambda>r   z{0} workersextrazgunicorn.workersZmetricr1   ZgaugemtypeN)rc   r   keysr?   spawn_workersrE   rD   rp   r   r   r   r   r   rB   r6   )r,   r>   rR   r   Zactive_worker_countr   r   r   rn     s    	
zArbiter.manage_workersc             C   s  |  j  d 7_  |  j |  j  |  j |  j |  j |  j d |  j |  j  } |  j j |  |  t	 j
   } | d k r | |  j | <| St	 j   } z"yU t j d |  j  |  j j d |  |  j j |  |  | j   t j d  Wn t k
 r   Yn t k
 rn} zO |  j j d d d t d	 | d
 t j t j j   t j |  j  WYd  d  } ~ XnD |  j j d  f | j st j |  j  n  t j d  Yn XWd  |  j j d |  y$ | j j    |  j j! |  |  Wn! |  j j" d t# j$    Yn XXd  S)Nr9   g       @r   zworker [%s]zBooting worker with pid: %sz'Exception while loading the applicationrk   Tz%sfilezException in worker processzWorker exiting (pid: %s)z Exception during worker exit:
%srl   )%r"   r<   rR   rU   r-   r@   r0   r   Zpre_forkr   r   r   rQ   r   rm   rA   rN   Z	post_forkZinit_processr'   r|   rx   r   rB   printstderrflushr   	exceptionZbootedr   r   rY   worker_exitr   	traceback
format_exc)r,   r   rR   Z
worker_pidr   r   r   r   r     sH    
"	zArbiter.spawn_workerc             C   sR   xK t  |  j t |  j j     D]' } |  j   t j d t j    q# Wd S)z        Spawn new workers as needed.

        This is where a worker process leaves the main loop
        of the master process.
        g?N)	r   r?   rc   r   r   r   r   rq   random)r,   r   r   r   r   r   E  s    )
zArbiter.spawn_workersc             C   s:   t  |  j j    } x | D] } |  j | |  q Wd S)z^        Kill all workers with the signal `sig`
        :attr sig: `signal.SIG*` value
        N)r   r   r   r   )r,   rg   Zworker_pidsrR   r   r   r   r   Q  s    zArbiter.kill_workersc             C   s   y t  j | |  Wn t k
 r } zv | j t j k r y: |  j j |  } | j j   |  j	 j
 |  |  d SWq t t f k
 r d SYq Xn    WYd d } ~ Xn Xd S)zj        Kill a worker

        :attr pid: int, worker pid
        :attr sig: `signal.SIG*` value
         N)r   killr   r   ZESRCHr   rp   r   rY   r0   r   r   )r,   rR   rg   r   r   r   r   r   r   Z  s    zArbiter.kill_worker)2__name__
__module____qualname____doc__r   r   r+   rU   r   r\   rd   splitr^   dictdirr   rs   r.   r/   r3   propertyr?   r    rX   rT   r   r`   r   r   r   r   r   r   r   r   r   ro   rf   rv   rq   rz   r   r   rr   r   rn   r   r   r   r   r   r   r   r   r
      sZ   	 #.

		
6)	r
   )
__future__r   r   r   r   r   r   r'   r   r   Zgunicorn.errorsr   r   Zgunicorn.pidfiler   Zgunicorn.sockr   Zgunicornr   r   r	   objectr
   r   r   r   r   <module>   s   