
    \eiym                         d 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	 ddl
mZmZ ddlmZmZmZmZ ddlmZmZ ddlmZ  G d	 d
      Zy)z
Dirty Arbiter Process

Asyncio-based arbiter that manages the dirty worker pool and routes
requests from HTTP workers to available dirty workers.
    N)util   )get_app_workers_attributeparse_dirty_app_spec)
DirtyErrorDirtyNoWorkersAvailableErrorDirtyTimeoutErrorDirtyWorkerError)DirtyProtocolmake_error_response)DirtyWorkerc                   <   e Zd ZdZdj	                         D  cg c]  }t        t        d|z         c}}}} ZdZd"dZ	d Z
d Zd	 Zd
 Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd#dZd Zd Zd Zd Zd Zd Zd Z d Z!d Z"d$d Z#d! Z$yc c}}}} w )%DirtyArbitera4  
    Dirty arbiter that manages the dirty worker pool.

    The arbiter runs an asyncio event loop and handles:
    - Spawning and managing dirty worker processes
    - Accepting connections from HTTP workers
    - Routing requests to available dirty workers
    - Monitoring worker health via heartbeat
    z HUP QUIT INT TERM USR1 USR2 CHLDzSIG%s   Nc                 
   || _         || _        d| _        t        j                         | _        || _        t        j                  d      | _	        |xs* t        j                  j                  | j                  d      | _        i | _        i | _        i | _        i | _        i | _        d| _        d| _        d| _        d| _        d| _        i | _        i | _        i | _        i | _        i | _        g | _        | j;                          y)z
        Initialize the dirty arbiter.

        Args:
            cfg: Gunicorn config
            log: Logger
            socket_path: Path to the arbiter's Unix socket
            pidfile: Well-known PID file location for orphan detection
        Nzgunicorn-dirty-)prefixzarbiter.sockr   T)cfglogpidosgetpidppidpidfiletempfilemkdtemptmpdirpathjoinsocket_pathworkersworker_socketsworker_connectionsworker_queuesworker_consumers_worker_rr_index
worker_agealive_server_loop_pending_requests	app_specsapp_worker_mapworker_app_map_app_rr_indices_pending_respawns_parse_app_specs)selfr   r   r   r   s        L/var/www/ceduoda/envi/lib/python3.12/site-packages/gunicorn/dirty/arbiter.py__init__zDirtyArbiter.__init__5   s     IIK	 &&.?@& 
"'',,KK+
  "$ " !

!#   !!# 	    c                 ,   | j                   j                  D ]H  }t        |      \  }}|	 t        |      }|||d| j                  |<   t               | j                  |<   J y# t        $ r'}| j
                  j                  d||       Y d}~Xd}~ww xY w)a  
        Parse all app specifications from config.

        Populates self.app_specs with parsed information about each app,
        including the import path and worker count limits.

        Worker count priority:
        1. Config override (e.g., "module:Class:2") - highest priority
        2. Class attribute (e.g., workers = 2 on the class)
        3. None (all workers) - default
        Nz,Could not read workers attribute from %s: %s)import_pathworker_countoriginal_spec)
r   
dirty_appsr   r   	Exceptionr   warningr+   setr,   )r1   specr6   r7   es        r2   r0   zDirtyArbiter._parse_app_specsg   s     HH'' 	5D(<T(B%K ##<[#IL  + ,!%+DNN;' 03uD,)	5 ! HH$$F#Q s   A##	B,BBc                    g }| j                   j                         D ]b  \  }}|d   }t        | j                  j	                  |t                           }||j                  |       L||k  sR|j                  |       d |S )a  
        Determine which apps a new worker should load.

        Returns a list of import paths for apps that need more workers.
        Apps with workers=None (all workers) are always included.
        Apps with worker limits are included only if they haven't
        reached their limit yet.

        Returns:
            List of import paths to load, or empty list if no apps need workers
        r7   )r+   itemslenr,   getr<   append)r1   	app_pathsr6   r=   r7   current_workerss         r2   _get_apps_for_new_workerz%DirtyArbiter._get_apps_for_new_worker   s     	!%!5!5!7 		.K/L!$"5"5"9"9+su"MNO #  - </  -		. r4   c                     t        |      | j                  |<   |D ]E  }|| j                  vrt               | j                  |<   | j                  |   j	                  |       G y)a?  
        Register which apps a worker has loaded.

        Updates both app_worker_map and worker_app_map to track the
        bidirectional relationship between workers and apps.

        Args:
            worker_pid: The PID of the worker
            app_paths: List of app import paths loaded by this worker
        N)listr-   r,   r<   addr1   
worker_pidrD   app_paths       r2   _register_worker_appsz"DirtyArbiter._register_worker_apps   s`     +/y/J'! 	:Ht22203##H-)--j9	:r4   c                     | j                   j                  |g       }|D ]/  }|| j                  v s| j                  |   j                  |       1 y)z
        Unregister a worker's apps when it exits.

        Removes the worker from all tracking maps.

        Args:
            worker_pid: The PID of the worker to unregister
        N)r-   popr,   discardrJ   s       r2   _unregister_workerzDirtyArbiter._unregister_worker   sV     ''++J;	 " 	BH4...##H-55jA	Br4   c                    t        j                         | _        | j                  j	                  d| j                         | j
                  rD	 t        | j
                  d      5 }|j                  t        | j                               ddd       | j                  j                  |        | j                          t        j                  d       	 t!        j"                  | j%                                | j)                          y# 1 sw Y   ~xY w# t        $ r&}| j                  j                  d|       Y d}~d}~ww xY w# t&        $ r Y Zw xY w# | j)                          w xY w)z&Run the dirty arbiter (blocking call).z Dirty arbiter starting (pid: %s)wNzFailed to write PID file: %szdirty-arbiter)r   r   r   r   infor   openwritestrIOErrorr;   r   on_dirty_startinginit_signalsr   _setproctitleasynciorun
_run_asyncKeyboardInterrupt_cleanup_sync)r1   fr>   s      r2   r]   zDirtyArbiter.run   s   99;8$((C <<D$,,, +GGCM*+ 	""4( 	 	?+	!KK)*  '+ + D  !?CCD ! 		  sT   D #%DD #E D
D 	E D;;E 	EE EE E$c                    | j                   D ]&  }t        j                  |t        j                         ( t        j                  t        j                  | j                         t        j                  t        j
                  | j                         t        j                  t        j                  | j                         t        j                  t        j                  | j                         t        j                  t        j                  | j                         t        j                  t        j                  | j                         y)zSet up signal handlers.N)
SIGNALSsignalSIG_DFLSIGTERM_signal_handlerSIGQUITSIGINTSIGHUPSIGUSR1SIGCHLD)r1   sigs     r2   rZ   zDirtyArbiter.init_signals   s    << 	/CMM#v~~.	/ 	fnnd&:&:;fnnd&:&:;fmmT%9%9:fmmT%9%9:fnnd&:&:;fnnd&:&:;r4   c                     |t         j                  k(  r+ j                  r j                  j                   fd       y|t         j                  k(  r j
                  j                          y|t         j                  k(  r+ j                  r j                  j                   fd       yd _         j                  r& j                  j                   j                         yy)zHandle signals.c                  J    t        j                   j                               S N)r\   create_task_handle_sigchldr1   s   r2   <lambda>z.DirtyArbiter._signal_handler.<locals>.<lambda>   s    G//0D0D0FG r4   Nc                  J    t        j                   j                               S rp   )r\   rq   reloadrs   s   r2   rt   z.DirtyArbiter._signal_handler.<locals>.<lambda>  s    G//> r4   F)
rd   rl   r)   call_soon_threadsaferk   r   reopen_filesrj   r'   	_shutdown)r1   rm   frames   `  r2   rg   zDirtyArbiter._signal_handler   s    &.. zz

//G &.. HH!!#&--zz

//>  
::JJ++DNN; r4   c                 R    | j                   r| j                   j                          yy)zInitiate async shutdown.N)r(   closers   s    r2   ry   zDirtyArbiter._shutdown  s    <<LL  r4   c                   K   t        j                         | _        t        j                  j                  | j                        rt        j                  | j                         t        j                  | j                  | j                         d{   | _
        t        j                  | j                  d       | j                  j                  d| j                         | j                          d{    t        j                  | j!                               }	 | j                  4 d{    | j                  j#                          d{    ddd      d{    |j'                          	 | d{    | j)                          d{    y7 7 7 o7 O7 A# 1 d{  7  sw Y   QxY w# t         j$                  $ r Y iw xY w7 V# t         j$                  $ r Y iw xY w7 Y# |j'                          	 | d{  7   n# t         j$                  $ r Y nw xY w| j)                          d{  7   w xY ww)z/Main async loop - start server, manage workers.)r   Ni  zDirty arbiter listening on %s)r\   get_running_loopr)   r   r   existsr   unlinkstart_unix_serverhandle_clientr(   chmodr   rT   manage_workersrq   _worker_monitorserve_foreverCancelledErrorcancelstop)r1   monitor_tasks     r2   r^   zDirtyArbiter._run_async  s    --/
 77>>$**+IId&&' %66!!
 
 	!!5)5t7G7GH !!### **4+?+?+AB	|| 3 3ll002223 3
 !""" ))+9
 	$323 3 3 3%% 		
 #))   !"""))  ))+s-  BIFA"I5F6'IF9 .F/F9 2F$F F$F9  F"!F9 %I6G ;G<G  IG-IIF9  F$"F9 $F6*F-+F62F9 9GG/ GG/ G G*'I)G**I/I HH	HI H# I "H##I 9H<:I  Ic                   K   | j                   rt        j                  d       d{    t        j                         | j
                  k7  r3| j                  j                  d       d| _         | j                          y| j                          d{    | j                          d{    | j                   ryy7 7 -7 w)z1Periodically check worker health and manage pool.g      ?Nz+Parent changed, shutting down dirty arbiterF)r'   r\   sleepr   getppidr   r   r;   ry   murder_workersr   rs   s    r2   r   zDirtyArbiter._worker_monitor8  s     jj--$$$ zz|tyy(  !NO"
 %%'''%%''' jj$ ('s:   %CB?A+CCC+C,C=CCCc                 z   K   | j                          | j                  r| j                          d{    yy7 w)z#Handle SIGCHLD - reap dead workers.N)reap_workersr'   r   rs   s    r2   rr   zDirtyArbiter._handle_sigchldG  s3     ::%%''' 's   0;9;c                 t  K   | j                   j                  d       	 | j                  rE	 t        j                  |       d{   }| j                  ||       d{    | j                  rE|j                          	 |j                          d{    y7 U# t
        j                  $ r Y Aw xY w7 V# t        $ r&}| j                   j                  d|       Y d}~qd}~ww xY w7 T# t        $ r Y yw xY w# |j                          	 |j                          d{  7   w # t        $ r Y w w xY wxY ww)z
        Handle a connection from an HTTP worker.

        Routes requests to available dirty workers and returns responses.
        Supports both regular responses and streaming (chunk-based) responses.
        z&New client connection from HTTP workerNzClient connection error: %s)r   debugr'   r   read_message_asyncr\   IncompleteReadErrorroute_requestr:   errorr|   wait_closed)r1   readerwritermessager>   s        r2   r   zDirtyArbiter.handle_clientN  s     	?@	**$1$D$DV$LLG
 ((&999 ** LLN((*** M22  : 	=HHNN8!<<	=
 +  LLN((*** s   D8B7 B BB 	B7 B5B7 0D8C+ C)C+ D8B B2/B7 1B22B7 7	C& C!C: !C&&C: )C+ +	C74D86C77D8:D5D&D" D&%D5&	D2/D51D22D55D8c                   K   |j                  dd      }|j                  d      }| j                  |       d{   }|h| j                  st        d      }n%|r| j                  rt        |      }nt        d      }t        ||      }t        j                  ||       d{    y|| j                  vr| j                  |       d{    | j                  |   }t        j                         j                         }	|j                  |||	f       d{    	 |	 d{    y7 7 7 a7 7 # t        $ rC}
t        |t!        d|
 |            }t        j                  ||       d{  7   Y d}
~
yd}
~
ww xY ww)a  
        Route a request to an available dirty worker via queue.

        Each worker has a dedicated queue and consumer task. Requests are
        submitted to the queue and processed sequentially by the consumer.

        For streaming responses, messages (chunks) are forwarded directly
        to the client_writer as they arrive from the worker.

        Args:
            request: Request message dict
            client_writer: StreamWriter to send responses to client
        idunknownrL   NzNo dirty workers availablezRequest failed: 	worker_id)rB   _get_available_workerr    r   r+   r   r   r   write_message_asyncr#   _start_worker_consumerr\   r~   create_futureputr:   r
   )r1   requestclient_writer
request_idrL   rK   r   responsequeuefuturer>   s              r2   r   zDirtyArbiter.route_requesti  sp     [[y1
;;z*  55h??
<<"#?@dnn4X>"#?@*:u=H33M8LLL T///--j999"":.))+99; ii-8999	MLL5 @ M
 : 	:  	M* #3A3!7:NH  33M8LLL	Ms   8FD)A(F#D+$'FD-AFD/FD3 #D1$D3 (F+F-F/F1D3 3	E?<3E:/E20E:5F:E??Fc                     K   t        j                          j                  <    fd}t        j                   |             }| j                  <   yw)z3Start a consumer task for a worker's request queue.c                    K   j                   ry	 j                          d {   \  } }}	 j                  | |       d {    |j                         s|j	                  d        j                          	 j                   rxy y 7 e7 G# t
        $ r+}|j                         s|j                  |       Y d }~Sd }~ww xY w# j                          w xY w# t        j                  $ r Y y w xY wwrp   )
r'   rB   _execute_on_workerdone
set_resultr:   set_exception	task_doner\   r   )r   r   r   r>   r   r1   rK   s       r2   consumerz5DirtyArbiter._start_worker_consumer.<locals>.consumer  s     **;@99;5F2G]F
*"55&    &{{}"--d3
 ) **5F
 % 4%{{}"0034 )-- s   C3C B
C B B%B *C :C3C3
C B 	C!B=8C =CC CC C0-C3/C00C3N)r\   Queuer#   rq   r$   )r1   rK   r   taskr   s   ``  @r2   r   z#DirtyArbiter._start_worker_consumer  sK     ).:&	$ ""8:.,0j)s   AAc                   K   |j                  dd      }	 | j                  |       d{   \  }}t        j                  ||       d{    	 	 t	        j
                  t        j                  |      | j                  j                         d{   }|j                  d      }	|	t        j                  k(  rt        j                  ||       d{    |	t        j                  k(  rt        j                  ||       d{    y|	t        j                  t        j                  fv rt        j                  ||       d{    y| j                   j#                  d|	       7 B7 $7 # t        j                  $ rL t        |t        d| j                  j                              }t        j                  ||       d{  7   Y yw xY w7 7 7 # t$        $ rq}
| j                   j'                  d||
       | j)                  |       t        |t+        d	|
 |
            }t        j                  ||       d{  7   Y d}
~
yd}
~
ww xY ww)a  
        Execute request on a specific worker (called by consumer).

        Handles both regular responses and streaming (chunk-based) responses.
        For streaming, chunk and end messages are forwarded directly to the
        client_writer as they arrive from the worker.
        r   r   N)timeoutzWorker timeouttypez$Unknown message type from worker: %sz Error executing on worker %s: %szWorker communication failed: r   )rB   _get_worker_connectionr   r   r\   wait_forr   r   dirty_timeoutTimeoutErrorr   r	   MSG_TYPE_CHUNKMSG_TYPE_ENDMSG_TYPE_RESPONSEMSG_TYPE_ERRORr   r;   r:   r   _close_worker_connectionr
   )r1   rK   r   r   r   r   r   r   r   msg_typer>   s              r2   r   zDirtyArbiter._execute_on_worker  s%     [[y1
0	M#'#>#>z#JJNFF33FGDDD $+$4$4%88@ $ 6 6% G #;;v. };;;';;M7SSS }999';;M7SSS  ? ? - < < > >';;M7SSS   !GRC 	 KD
 ++ 2")*:DHH<R<RS H (;;M8TTT T
 T T  	MHHNN=z1M))*5* #@!D+57H
  33M8LLL	Ms   IG E, G E/G AE4 E2E4 =G G1G GG I;G G	G IG /G 2E4 4AG
GGG IGG G G 	I&A!II
IIIIc                   K   |r4| j                   r(|| j                  v rt        | j                  |         }n$yt        | j                  j	                               }|sy|rG| j                   r;| j
                  j                  |d      }|dz   t        |      z  | j
                  |<   n"| j                  }|dz   t        |      z  | _        ||t        |      z     S w)a  
        Get an available worker PID using round-robin selection.

        If app_path is provided, only returns workers that have loaded
        that specific app. Uses per-app round-robin to ensure fair
        distribution among eligible workers.

        Args:
            app_path: Optional import path of the target app. If None,
                     returns any worker using global round-robin.

        Returns:
            Worker PID or None if no eligible workers are available.
        Nr   r   )	r+   r,   rH   r    keysr.   rB   rA   r%   )r1   rL   eligible_pidsidxs       r2   r   z"DirtyArbiter._get_available_worker  s        4... $T%8%8%B C  !!2!2!45M &&**8Q7C.1Ag]9K-KD  *''C%(1WM0B$BD!S3}#5566s   CCc                   K   || j                   v r| j                   |   S | j                  j                  |      }|st        d|       t	        d      D ]@  }t
        j                  j                  |      r n-t        j                  d       d{    B t        d|       t        j                  |       d{   \  }}||f| j                   |<   ||fS 7 I7 w)z%Get or create connection to a worker.zNo socket for worker 2   皙?NzWorker socket not ready: )r"   r!   rB   r   ranger   r   r   r\   r   open_unix_connection)r1   rK   r   _r   r   s         r2   r   z#DirtyArbiter._get_worker_connection  s     000**:66))--j94ZLABB r 	HAww~~k*--$$$	H
 8FGG&;;KHH/5v.>
+v~ % Is$   BC C,C ?C C C c                 ~    || j                   v r/| j                   j                  |      \  }}|j                          yy)zClose connection to a worker.N)r"   rO   r|   )r1   rK   _readerr   s       r2   r   z%DirtyArbiter._close_worker_connection2  s8    000"5599*EOGVLLN 1r4   c                 |   K    j                   sy j                  j                  } j                   rmt         j                        |k  rU j                         }|nBt        j                  d       d{     j                   rt         j                        |k  rUt         j                        |kD  rt         j                  j                          fd      } j                  |t        j                         t        j                  d       d{    t         j                        |kD  r~yy7 7 !w)z%Maintain the number of dirty workers.Nr   c                 6    j                   |    j                  S rp   )r    age)pr1   s    r2   rt   z-DirtyArbiter.manage_workers.<locals>.<lambda>K  s    4<<?+>+> r4   )key)r'   r   dirty_workersrA   r    spawn_workerr\   r   minr   kill_workerrd   rf   )r1   num_workersresult
oldest_pids   `   r2   r   zDirtyArbiter.manage_workers8  s     zzhh,, jjS.<&&(F~--$$$ jjS.< $,,+-T\\..0!>@JZ8--$$$ $,,+- % %s1   A3D<6D87(D< A8D<D:D<6D<:D<c                    | j                   r| j                   j                  d      }n| j                         }|s| j                  j	                  d       y| xj
                  dz  c_        t        j                  j                  | j                  d| j
                   d      }t        | j
                  | j                  || j                  | j                  |      }t        j                         }|dk7  rr||_        || j                  |<   || j                  |<   | j!                  ||       | j                  j#                  | |       | j                  j%                  d||       |S t        j&                         |_        	 t)        j*                  d	| j                  j,                   d
       |j/                          t1        j2                  d       y# t4        $ r  t6        $ r^ | j                  j9                  d       |j:                  st1        j2                  | j<                         t1        j2                  d       Y yw xY w)aW  
        Spawn a new dirty worker.

        Worker app assignment follows these priorities:
        1. If there are pending respawns (from dead workers), use those apps
        2. Otherwise, determine apps for a new worker based on allocation

        Returns:
            Worker PID in parent process, or None if no apps need workers
        r   z)No apps need more workers, skipping spawnNr   zworker-z.sock)r   r   rD   r   r   r   z,Spawned dirty worker (pid: %s) with apps: %szdirty-worker []z!Exception in dirty worker process)r/   rO   rF   r   r;   r&   r   r   r   r   r   r   r   forkr    r!   rM   dirty_post_forkrT   r   r   r[   	proc_nameinit_processsysexit
SystemExitr:   	exceptionbootedWORKER_BOOT_ERROR)r1   rD   r   workerr   s        r2   r   zDirtyArbiter.spawn_workerO  s    !!..2215I 557IHHHI1ggllKK74??"359
 #
 ggi!8FJ &DLL'2D$ &&sI6HH$$T62HHMMHy*J YY[

	0B0B/C1EF!HHQK 	 	HHBC==//0HHRL		s   AG A-IIc                     	 t        j                  ||       y# t        $ r=}|j                  t        j                  k(  r| j                  |       Y d}~yY d}~yd}~ww xY w)zKill a worker by PID.N)r   killOSErrorerrnoESRCH_cleanup_worker)r1   r   rm   r>   s       r2   r   zDirtyArbiter.kill_worker  sK    	*GGC 	*ww%++%$$S)) &	*s    	A.AAc                    | j                  |       || j                  v r*| j                  |   j                          | j                  |= | j                  j	                  |d       || j
                  v r5t        | j
                  |         }|r| j                  j                  |       | j                  |       | j                  j	                  |d      }|r| j                  j                  | |       | j                  j	                  |d      }|r7t        j                  j!                  |      r	 t        j"                  |       yyy# t$        $ r Y yw xY w)z
        Clean up after a worker exits.

        Saves the dead worker's app list to pending respawns so the
        replacement worker gets the same apps.
        N)r   r$   r   r#   rO   r-   rH   r/   rC   rQ   r    r   dirty_worker_exitr!   r   r   r   r   r   )r1   r   	dead_appsr   r   s        r2   r   zDirtyArbiter._cleanup_worker  s.    	%%c* $'''!!#&--/%%c* 	sD) $%%%T0056I&&--i8 	$!!#t,HH&&tV4))--c48277>>+6		+& 7;  s   2E
 
	EEc                 ,  K   | j                   j                  syt        | j                  j	                               D ]  \  }}	 t        j                         |j                  j                         z
  | j                   j                  k  rN	 |j                  sD| j                  j                  d|       d|_        | j                  |t        j                          | j                  |t        j"                          y# t        t        f$ r Y w xY ww)z!Kill workers that have timed out.NzDIRTY WORKER TIMEOUT (pid:%s)T)r   r   rH   r    r@   time	monotonictmplast_updater   
ValueErrorabortedr   criticalr   rd   SIGABRTSIGKILL)r1   r   r   s      r2   r   zDirtyArbiter.murder_workers  s     xx%% 2 2 45 	6KC>>#fjj&<&<&>>$((BXBXX Y
 >>!!"A3G!%  fnn5  fnn5	6 Z( s,   ADAC?
A5D?DDDDc                 \   	 	 t        j                  dt         j                        \  }}|syd}t        j                  |      rt        j                  |      }nGt        j
                  |      r2t        j                  |      }| j                  j                  d||       || j                  k(  r| j                  j                  d|       | j                  |       | j                  j                  d|       # t        $ r(}|j                  t        j                  k7  r Y d}~yd}~ww xY w)zReap dead worker processes.r   Nz)Dirty worker (pid:%s) killed by signal %sz$Dirty worker failed to boot (pid:%s)zDirty worker exited (pid:%s))r   waitpidWNOHANG	WIFEXITEDWEXITSTATUSWIFSIGNALEDWTERMSIGr   r;   r   r   r   rT   r   r   ECHILD)r1   wpidstatusexitcoderm   r>   s         r2   r   zDirtyArbiter.reap_workers  s    	!zz"bjj9f<<'!~~f5H^^F+++f-CHH$$%P%)30 t555HHNN#I4P$$T*<dC# $  	ww%,,& '	s   *C: CC: :	D+D&&D+c                   K   | j                   j                  d       t        | j                  j                        D ]/  }| j                          t        j                  d       d{    1 t        | j                  j                               }|| j                  j                  d D ]"  }| j                  |t        j                         $ y7 hw)z!Reload workers (SIGHUP handling).zReloading dirty workersr   N)r   rT   r   r   r   r   r\   r   rH   r    r   r   rd   rf   )r1   r   old_workersr   s       r2   rv   zDirtyArbiter.reload  s     /0 txx--. 	%A--$$$	%
 4<<,,./txx5567 	2CS&..1	2	 %s   A&C(C)A)Cc                   K   | j                   j                         D ]  }|j                           |rt        j                  nt        j
                  }t        j                         | j                  j                  z   }t        | j                  j                               D ]  }| j                  ||        | j                  rht        j                         |k  rQ| j                          t        j                  d       d{    | j                  rt        j                         |k  rQt        | j                  j                               D ]"  }| j                  |t        j                          $ | j                          y7 w)zStop all workers.r   N)r$   valuesr   rd   rf   rh   r   r   dirty_graceful_timeoutrH   r    r   r   r   r\   r   r   )r1   gracefulr   rm   limitr   s         r2   r   zDirtyArbiter.stop  s!     ))002 	DKKM	 !)fnnfnn		dhh=== ))+, 	'CS#&	' lltyy{U2--$$$ lltyy{U2
 ))+, 	2CS&..1	2 %s   DFF'F-AFc                    | j                   rIt        j                  j                  | j                         r 	 t        j                  | j                          t        j                  j                  | j                        r 	 t        j                  | j                         	 t        j                  | j                        D ]?  }t        j                  t        j                  j                  | j                  |             A t        j                  | j                         | j                  j                  d| j                         y# t
        $ r Y w xY w# t
        $ r Y w xY w# t
        $ r Y Pw xY w)zSynchronous cleanup on exit.zDirty arbiter exiting (pid: %s)N)r   r   r   r   r   r   r   listdirr   r   rmdirr   rT   r   )r1   ra   s     r2   r`   zDirtyArbiter._cleanup_sync  s    <<BGGNN4<<8		$,,'
 77>>$**+		$**+
	ZZ, 8		"'',,t{{A678HHT[[! 	7B%      		s6   E  E  B E% 	EE	E"!E"%	E10E1)NNrp   )T)%__name__
__module____qualname____doc__splitgetattrrd   rc   r   r3   r0   rF   rM   rQ   r]   rZ   rg   ry   r^   r   rr   r   r   r   r   r   r   r   r   r   r   r   r   r   rv   r   r`   ).0xr  rd   s   0000r2   r   r   $   s     2779; ;wvw{+ ;G 0 d 5D6:$B"!:
<<8!
%N((62Mh14:Mx(7T*%.?B*"H6&22.C};s   B
r   )r  r\   r   r   rd   r   r   r   gunicornr   appr   r   errorsr   r   r	   r
   protocolr   r   r   r   r    r4   r2   <module>r     sI   
   	  
    @   AC ACr4   