
     i1                         S r SSKrSSKrSSKrSSKrSSKJr  SSKJrJ	r	J
r
  \" 5       rSS0rS rS rS	 rS
 r " S S5      rg)a  
Control Socket Server

Runs in the arbiter process and accepts commands via Unix socket.
Uses asyncio in a background thread to handle client connections.

Fork Safety:
    This server uses os.register_at_fork() to properly handle fork() calls.
    Before fork: the asyncio thread is stopped to prevent lock issues.
    After fork in parent: the server is restarted.
    After fork in child: references are cleared (workers don't need the control server).
    N)CommandHandlers)ControlProtocolmake_responsemake_error_responsefork_handlers_registeredFc                  x    [         S   (       a  gS[         S'   [        R                  " [        [        [
        S9  g)z,Register fork handlers once at module level.r   NT)beforeafter_in_parentafter_in_child)_module_stateosregister_at_fork_before_fork_after_fork_parent_after_fork_child     E/var/www/ias/venv/lib/python3.13/site-packages/gunicorn/ctl/server.py_register_fork_handlersr   %   s0    /004M,-*(r   c                  P    [        [        5       H  n U R                  5         M     g)z7Called before fork() - stop all active control servers.N)list_active_servers_stop_for_forkservers    r   r   r   2   s    ' (r   c                  P    [        [        5       H  n U R                  5         M     g)z<Called in parent after fork() - restart all control servers.N)r   r   _restart_after_forkr   s    r   r   r   8   s    '""$ (r   c                  ,    [         R                  5         g)z2Called in child after fork() - cleanup references.N)r   clearr   r   r   r   r   >   s     r   c                       \ rS rSrSrSS jrS rS rS rS r	S r
S	 rS
 rS rS\S\4S jrS\S\4S jrS\S\4S jrS\S\4S jrS\S\4S jrSrg)ControlSocketServerE   a/  
Control socket server running in arbiter process.

The server runs an asyncio event loop in a background thread,
accepting connections and dispatching commands to handlers.

Fork safety is handled via os.register_at_fork() - the server
automatically stops before fork and restarts after in the parent.
c                     Xl         X l        X0l        [        U5      U l        SU l        SU l        SU l        SU l        SU l	        [        5         g)z
Initialize control socket server.

Args:
    arbiter: The Gunicorn arbiter instance
    socket_path: Path for the Unix socket
    socket_mode: Permission mode for socket (default 0o600)
NF)arbitersocket_pathsocket_moder   handlers_server_loop_thread_running_was_running_before_forkr   )selfr$   r%   r&   s       r   __init__ControlSocketServer.__init__P   sM     &&'0
(-% 	 !r   c                     U R                   (       a  gSU l         [        R                  " U R                  SS9U l        U R                  R                  5         [        R                  U 5        g)z:Start server in background thread with asyncio event loop.NTtargetdaemon)r+   	threadingThread	_run_loopr*   startr   addr-   s    r   r7   ControlSocketServer.startg   sK    == ''t~~dK 	D!r   c                    [         R                  U 5        U R                  (       d  gSU l        U R                  (       a6  U R                  (       a%  U R                  R                  U R                  5        U R                  (       a   U R                  R                  SS9  SU l        [        R                  R                  U R                  5      (       a"   [        R                  " U R                  5        gg! [         a     gf = f)zStop server and cleanup socket.NF       @timeout)r   discardr+   r)   r(   call_soon_threadsafe	_shutdownr*   joinr   pathexistsr%   unlinkOSErrorr9   s    r   stopControlSocketServer.stops   s     	%}}::$,,JJ++DNN;<<LLc*DL 77>>$**++		$**+ ,  s    C8 8
DDc                    U R                   (       d  SU l        gSU l        SU l         U R                  (       a7  U R                  (       a&   U R                  R	                  U R
                  5        U R                  (       a   U R                  R                  SS9  SU l        SU l        SU l        g! [         a     NLf = f)z1Stop server before fork (called by fork handler).FNTr<   r=   )	r+   r,   r)   r(   r@   rA   RuntimeErrorr*   rB   r9   s    r   r   "ControlSocketServer._stop_for_fork   s    }},1D)(,%::$,,

//?
 <<LLc*DL
   s   %B0 0
B=<B=c                     U R                   (       d  gSU l         SU l        [        R                  " U R                  SS9U l        U R
                  R                  5         g)z=Restart server in parent after fork (called by fork handler).NFTr1   )r,   r+   r4   r5   r6   r*   r7   r9   s    r   r   'ControlSocketServer._restart_after_fork   sE    ,,(-% ''t~~dKr   c                 \    U R                   (       a  U R                   R                  5         gg)z0Shutdown server (called from event loop thread).N)r(   closer9   s    r   rA   ControlSocketServer._shutdown   s    <<LL  r   c                 4    [         R                  " U R                  5       5        g! [         af  nU R                  (       aK  U R
                  R                  (       a+  U R
                  R                  R                  SU5         SnAg SnAg SnAgSnAff = f)z0Run the asyncio event loop in background thread.zControl server error: %sN)asynciorun_serve	Exceptionr+   r$   logerror)r-   es     r   r6   ControlSocketServer._run_loop   sd    	FKK& 	F}}!1!1  &&'A1EE "2}	Fs   $' 
BABBc                   #    [         R                  " 5       U l        [        R                  R                  U R                  5      nU(       a9  [        R                  R                  U5      (       d  [        R                  " USS9  [        R                  R                  U R                  5      (       a   [        R                  " U R                  5        [         R                  " U R                  U R                  S9I Sh  vN U l        [        R                  " U R                  U R                  5        U R                  R                   (       a0  U R                  R                   R#                  SU R                  5         U R                   ISh  vN   U R                  R%                  5       I Sh  vN   SSS5      ISh  vN   [        R                  R                  U R                  5      (       a"   [        R                  " U R                  5        gg GN N Nj N\! , ISh  vN  (       d  f       Nq= f! [         R&                   a     Nf = f! [(         a     gf = f! [        R                  R                  U R                  5      (       a2   [        R                  " U R                  5        f ! [(         a     f f = ff = f7f)zMain async server loop.i  )mode)rC   NzControl socket listening at %s)rR   get_running_loopr)   r   rC   dirnamer%   rD   makedirsrE   start_unix_server_handle_clientr(   chmodr&   r$   rV   infoserve_foreverCancelledErrorrF   )r-   
socket_dirs     r   rT   ControlSocketServer._serve   s    --/
 WW__T%5%56
bggnnZ88KK
/ 77>>$**++IId&&' %66!!
 
 	!!4#3#34<<LL!!"B"&"2"24
	|||ll00222 $|
 ww~~d..//IId../ 0%
 $2 $|||%% 		   ww~~d..//IId../  0s   C>K HA?KH< HH< H"3H4H"8H< H H< .K7 I KH< H" H< "H9(H+)H95H< 8I& 9H< <II& II& 
I# K"I##K&/K J76K7
KKKKKc                 R  #     U R                   (       a|   [        R                  " [        R                  " U5      SS9I Sh  vN nU R                  U5      I Sh  vN n[        R                  " X$5      I Sh  vN   U R                   (       a  M|  UR                  5          UR                  5       I Sh  vN   g Nx! [        R
                   a     MC  [        R                   a     MY  [         a     Me  f = f N N! [         aK  nU R                  R                  (       a&  U R                  R                  R                  SU5         SnANSnAff = f N! [         a     gf = f! UR                  5          UR                  5       I Sh  vN    f ! [         a     f f = f= f7f)zd
Handle client connection.

Args:
    reader: asyncio StreamReader
    writer: asyncio StreamWriter
g     r@r=   NzControl client error: %s)r+   rR   wait_forr   read_message_asyncTimeoutErrorIncompleteReadErrorrU   	_dispatchwrite_message_asyncr$   rV   debugrO   wait_closed)r-   readerwritermessageresponserX   s         r   r`   "ControlSocketServer._handle_client   s]    	--$+$4$4'::6B %% G "&!88 &99&KKK) ---4 LLN((***5 ++ 22   
 9 L 	F||  &&'A1E	F +  LLN((*** s  F'C> ,B= B;B= C> C:C> 9C<:C> F'"E 5E6E :F';B= =C7C> E( C7'C> (E( *	C73C> 4E( 6C77C> <C> >
EAE	E( EE( E 
E%"F'$E%%F'(F$:FFFF$
F!F$ F!!F$$F'rr   returnc                   #    UR                  SS5      nUR                  SS5      R                  5       nUR                  S/ 5      nU(       d  [        US5      $  [        R                  " U5      nU(       a  UR                  S U 5       5        U(       d  [        US5      $ U R                  U5      n[        X&5      $ ! [         a  n[        USU 35      s S	nA$ S	nAf[         aY  nU R                  R                  (       a%  U R                  R                  R                  S
5        [        USU 35      s S	nA$ S	nAff = f7f)zu
Dispatch command to appropriate handler.

Args:
    message: Request message dict

Returns:
    Response dictionary
idr   command argsEmpty commandc              3   8   #    U  H  n[        U5      v   M     g 7f)N)str).0as     r   	<genexpr>0ControlSocketServer._dispatch.<locals>.<genexpr>  s     2TSVVTs   zInvalid argument: NzCommand errorzCommand failed: )getstripr   shlexsplitextend_execute_commandr   
ValueErrorrU   r$   rV   	exception)r-   rr   
request_idrx   rz   partsresultrX   s           r   rl   ControlSocketServer._dispatch	  s     [[q)
++i,224{{62&&z?CC	KKK(E2T22*:GG **51F 44 	M&z5Gs3KLL 	K||  **?;&z5EaS3IJJ	Ks\   AEAB? "E#B? >E?
E	CEEE*AD>8E9E>EEr   c                    U(       d  [        S5      eUS   R                  5       nUSS nUS:X  a  U R                  U5      $ US:X  a  U R                  U5      $ US:X  a  U R	                  U5      $ US:X  a  U R
                  R                  5       $ US	:X  a  U R
                  R                  5       $ US
:X  a)  U(       a  US   OSnU R
                  R                  U5      $ US:X  a  U R
                  R                  5       $ [        SU 35      e)z
Execute a parsed command.

Args:
    parts: Command parts (e.g., ["show", "workers"])

Returns:
    Handler result dictionary
r{   r      NshowworkerdirtyreloadreopenshutdowngracefulhelpzUnknown command: )
r   lower_handle_show_handle_worker_handle_dirtyr'   r   r   r   r   )r-   r   cmdrestr[   s        r   r   $ControlSocketServer._execute_command.  s    _--AhnnQRy &=$$T**H_&&t,,G^%%d++H_==''))H_==''))J"47
D==))$//F]==%%''0677r   rz   c                    U(       d  [        S5      eUS   R                  5       nUS:X  a  U R                  R                  5       $ US:X  a  U R                  R	                  5       $ US:X  a  U R                  R                  5       $ US:X  a  U R                  R                  5       $ US:X  a  U R                  R                  5       $ US:X  a  U R                  R                  5       $ [        S	U 35      e)
zHandle 'show' commands.z>Missing show target (all|workers|dirty|config|stats|listeners)r   allworkersr   configstats	listenerszUnknown show target: )	r   r   r'   show_allshow_workers
show_dirtyshow_config
show_statsshow_listeners)r-   rz   r2   s      r   r    ControlSocketServer._handle_showQ  s    ]^^aU?==))++y ==--//w==++--x==,,..w==++--{"==//114VH=>>r   c                    U(       d  [        S5      eUS   R                  5       nUSS nUS:X  a2  U(       a  [        US   5      OSnU R                  R	                  U5      $ US:X  a2  U(       a  [        US   5      OSnU R                  R                  U5      $ US:X  a;  U(       d  [        S5      e[        US   5      nU R                  R                  U5      $ [        S	U 35      e)
zHandle 'worker' commands.z'Missing worker action (add|remove|kill)r   r   Nr8   removekillzMissing PID for worker killzUnknown worker action: )r   r   intr'   
worker_addworker_removeworker_kill)r-   rz   actionaction_argscountpids         r   r   "ControlSocketServer._handle_workerg  s    FGGa12hU?+6CA'AE==++E22x+6CA'AE==..u55v !>??k!n%C==,,S116vh?@@r   c                 R   U(       d  [        S5      eUS   R                  5       nUSS nUS:X  a2  U(       a  [        US   5      OSnU R                  R	                  U5      $ US:X  a2  U(       a  [        US   5      OSnU R                  R                  U5      $ [        SU 35      e)zHandle 'dirty' commands.z!Missing dirty action (add|remove)r   r   Nr8   r   zUnknown dirty action: )r   r   r   r'   	dirty_adddirty_remove)r-   rz   r   r   r   s        r   r   !ControlSocketServer._handle_dirty}  s    @AAa12hU?+6CA'AE==**511x+6CA'AE==--e445fX>??r   )	r)   r+   r(   r*   r,   r$   r'   r&   r%   N)i  )__name__
__module____qualname____firstlineno____doc__r.   r7   rG   r   r   rA   r6   rT   r`   dictrl   r   r   r   r   r   __static_attributes__r   r   r   r!   r!   E   s    ".
"2.!
F$L'R#Kt #K #KJ!8d !8t !8F? ?$ ?,A4 AD A,@$ @4 @r   r!   )r   rR   r   r   r4   gunicorn.ctl.handlersr   gunicorn.ctl.protocolr   r   r   setr   r   r   r   r   r   r!   r   r   r   <module>r      sZ   
  	   1  %+U3
 %G@ G@r   