
    [i1                         d 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	m
Z
  e       ZddiZd Zd Zd	 Zd
 Z G d d      Zy)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                  r    t         d   rydt         d<   t        j                  t        t        t
               y)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     d/var/www/html/userprofiledev.eatanceapp.com/venv/lib/python3.12/site-packages/gunicorn/ctl/server.py_register_fork_handlersr   %   s0    /004M,-*(r   c                  L    t        t              D ]  } | j                           y)z7Called before fork() - stop all active control servers.N)list_active_servers_stop_for_forkservers    r   r   r   2   s    ' (r   c                  L    t        t              D ]  } | j                           y)z<Called in parent after fork() - restart all control servers.N)r   r   _restart_after_forkr   s    r   r   r   8   s    '""$ (r   c                  ,    t         j                          y)z2Called in child after fork() - cleanup references.N)r   clearr   r   r   r   r   >   s     r   c                       e 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edefdZdedefdZdedefdZdedefdZdedefdZy)ControlSocketServeraG  
    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                     || _         || _        || _        t        |      | _        d| _        d| _        d| _        d| _        d| _	        t                y)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__zControlSocketServer.__init__P   sS     &&'0
(-% 	 !r   c                     | j                   ryd| _         t        j                  | j                  d      | _        | j                  j                          t        j                  |        y)z:Start server in background thread with asyncio event loop.NTtargetdaemon)r*   	threadingThread	_run_loopr)   startr   addr,   s    r   r5   zControlSocketServer.startg   sK    == ''t~~dK 	D!r   c                    t         j                  |        | j                  syd| _        | j                  r1| j                  r%| j                  j                  | j                         | j                  r#| j                  j                  d       d| _        t        j                  j                  | j                        r!	 t        j                  | j                         yy# t        $ r Y yw xY w)zStop server and cleanup socket.NF       @timeout)r   discardr*   r(   r'   call_soon_threadsafe	_shutdownr)   joinr   pathexistsr$   unlinkOSErrorr7   s    r   stopzControlSocketServer.stops   s     	%}}::$,,JJ++DNN;<<LLc*DL 77>>$**+		$**+ ,  s    C! !	C-,C-c                 \   | j                   sd| _        yd| _        d| _         | j                  r2| j                  r&	 | j                  j	                  | j
                         | j                  r#| j                  j                  d       d| _        d| _        d| _        y# t        $ r Y Iw xY w)z1Stop server before fork (called by fork handler).FNTr9   r:   )	r*   r+   r(   r'   r=   r>   RuntimeErrorr)   r?   r7   s    r   r   z"ControlSocketServer._stop_for_fork   s    }},1D)(,%::$,,

//?
 <<LLc*DL
   s   %B 	B+*B+c                     | j                   syd| _         d| _        t        j                  | j                  d      | _        | j
                  j                          y)z=Restart server in parent after fork (called by fork handler).NFTr/   )r+   r*   r2   r3   r4   r)   r5   r7   s    r   r   z'ControlSocketServer._restart_after_fork   sE    ,,(-% ''t~~dKr   c                 R    | j                   r| j                   j                          yy)z0Shutdown server (called from event loop thread).N)r'   closer7   s    r   r>   zControlSocketServer._shutdown   s    <<LL  r   c                    	 t        j                  | j                                y# t        $ r\}| j                  rF| j
                  j                  r+| j
                  j                  j                  d|       Y d}~yY d}~yY d}~yd}~ww xY w)z0Run the asyncio event loop in background thread.zControl server error: %sN)asynciorun_serve	Exceptionr*   r#   logerror)r,   es     r   r4   zControlSocketServer._run_loop   sd    	FKK& 	F}}!1!1  &&'A1EE "2}	Fs   #& 	BABBc                 L  K   t        j                         | _        t        j                  j                  | j                        }|r6t        j                  j                  |      st        j                  |d       t        j                  j                  | j                        rt        j                  | j                         t        j                  | j                  | j                         d{   | _        t        j                  | j                  | j                         | j                  j                   r0| j                  j                   j#                  d| j                         	 | j                  4 d{    | j                  j%                          d{    ddd      d{    t        j                  j                  | j                        r!	 t        j                  | j                         yy7 7 7 d7 V# 1 d{  7  sw Y   fxY w# t         j&                  $ r Y ~w xY w# t(        $ r Y yw xY w# t        j                  j                  | j                        r0	 t        j                  | j                         w # t(        $ r Y w w xY ww xY ww)zMain async server loop.i  )mode)r@   NzControl socket listening at %s)rK   get_running_loopr(   r   r@   dirnamer$   rA   makedirsrB   start_unix_server_handle_clientr'   chmodr%   r#   rO   infoserve_foreverCancelledErrorrC   )r,   
socket_dirs     r   rM   zControlSocketServer._serve   s    --/
 WW__T%5%56
bggnnZ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   C1J$3H 4A9J$.H >H?H H	 H!H	%H 0H1H 5)J$H7 >J$H H	H 	HHHH H41I 3H44I 7	I J$IJ$*J!1JJ!	JJ!JJ!!J$c                 "  K   	 | j                   rw	 t        j                  t        j                  |      d       d{   }| j                  |       d{   }t        j                  ||       d{    | j                   rw|j                          	 |j                          d{    y7 r# t        j
                  $ r Y At        j                  $ r Y Ut        $ r Y _w xY w7 7 v# t        $ rF}| j                  j                  r&| j                  j                  j                  d|       Y d}~d}~ww xY w7 # 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 client connection.

        Args:
            reader: asyncio StreamReader
            writer: asyncio StreamWriter
        g     r@r:   NzControl client error: %s)r*   rK   wait_forr   read_message_asyncTimeoutErrorIncompleteReadErrorrN   	_dispatchwrite_message_asyncr#   rO   debugrI   wait_closed)r,   readerwritermessageresponserQ   s         r   rX   z"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. -B3 B1B3 C. C*C. 5C,6C. FE +E ,E 0F1B3 3C'C. C'C. C'$C. &C''C. ,C. .	D=7<D83E 8D==E  E 	EFEFF#E=6E97E=<F=	F	FF		FFri   returnc                 d  K   |j                  dd      }|j                  dd      j                         }|j                  dg       }|st        |d      S 	 t        j                  |      }|r|j                  d |D               |st        |d      S | j                  |      }t        ||      S # t        $ r}t        |d|       cY d	}~S d	}~wt        $ rT}| j                  j                  r%| j                  j                  j                  d
       t        |d|       cY d	}~S d	}~ww xY ww)z
        Dispatch command to appropriate handler.

        Args:
            message: Request message dict

        Returns:
            Response dictionary
        idr   command argsEmpty commandc              3   2   K   | ]  }t        |        y w)N)str).0as     r   	<genexpr>z0ControlSocketServer._dispatch.<locals>.<genexpr>  s     2TSVTs   zInvalid argument: NzCommand errorzCommand failed: )getstripr   shlexsplitextend_execute_commandr   
ValueErrorrN   r#   rO   	exception)r,   ri   
request_idrn   rp   partsresultrQ   s           r   rc   zControlSocketServer._dispatch	  s     [[q)
++i,224{{62&&z?CC	KKK(E2T22*:GG **51F V44 	M&z5Gs3KLL 	K||  **?;&z5EaS3IJJ	Ks[   AD0<B0 D0B0 /D00	D-9CD-D0D-A	D("D-#D0(D--D0r   c                    |st        d      |d   j                         }|dd }|dk(  r| j                  |      S |dk(  r| j                  |      S |dk(  r| j	                  |      S |dk(  r| j
                  j                         S |d	k(  r| j
                  j                         S |d
k(  r$|r|d   nd}| j
                  j                  |      S |dk(  r| j
                  j                         S t        d|       )z
        Execute a parsed command.

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

        Returns:
            Handler result dictionary
        rq   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restrS   s        r   r|   z$ControlSocketServer._execute_command.  s    _--AhnnQRy &=$$T**H_&&t,,G^%%d++H_==''))H_==''))J"47
D==))$//F]==%%''0677r   rp   c                    |st        d      |d   j                         }|dk(  r| j                  j                         S |dk(  r| j                  j	                         S |dk(  r| j                  j                         S |dk(  r| j                  j                         S |dk(  r| j                  j                         S |dk(  r| j                  j                         S t        d	|       )
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,   rp   r0   s      r   r   z ControlSocketServer._handle_showQ  s    ]^^aU?==))++y ==--//w==++--x==,,..w==++--{"==//114VH=>>r   c                    |st        d      |d   j                         }|dd }|dk(  r-|rt        |d         nd}| j                  j	                  |      S |dk(  r-|rt        |d         nd}| j                  j                  |      S |dk(  r6|st        d      t        |d         }| j                  j                  |      S t        d	|       )
zHandle 'worker' commands.z'Missing worker action (add|remove|kill)r   r   Nr6   removekillzMissing PID for worker killzUnknown worker action: )r}   r   intr&   
worker_addworker_removeworker_kill)r,   rp   actionaction_argscountpids         r   r   z"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                 0   |st        d      |d   j                         }|dd }|dk(  r-|rt        |d         nd}| j                  j	                  |      S |dk(  r-|rt        |d         nd}| j                  j                  |      S t        d|       )zHandle 'dirty' commands.z!Missing dirty action (add|remove)r   r   Nr6   r   zUnknown dirty action: )r}   r   r   r&   	dirty_adddirty_remove)r,   rp   r   r   r   s        r   r   z!ControlSocketServer._handle_dirty}  s    @AAa12hU?+6CA'AE==**511x+6CA'AE==--e445fX>??r   N)i  )__name__
__module____qualname____doc__r-   r5   rD   r   r   r>   r4   rM   rX   dictrc   r   r|   r   r   r   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   rK   r   ry   r2   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   