
    AҐi8W                        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 d dlmZ d dlmZ ddlmZ dd	lmZ dd
lmZ ddlmZ ddlmZ  G d d      Z G d d      Z G d dej.                        Zy)    )futuresN)deque)datetime)partial   )base   )http)util)sock)wsgic                   $    e Zd Zd Zd Zd Zd Zy)TConnc                     || _         || _        || _        || _        d | _        d | _        d| _        d| _        | j                  j                  d       y )NF)	cfgr   clientservertimeoutparserinitializedis_http2setblocking)selfr   r   r   r   s        Q/var/www/descvideos/venv/lib/python3.12/site-packages/gunicorn/workers/gthread.py__init__zTConn.__init__#   sO    	  			e$    c                    | j                   ry d| _         | j                  j                  d       | j                  -| j                  j
                  rt        j                  | j                  | j                        | _        | j                  j                  s| j                  j                          t        j                  | j                        r^d| _
        t        j                  | j                  | j                  | j                  d      | _        | j                  j                          y t        j                  | j                  | j                  | j                        | _        y y )NT)http2_connection)r   r   r   r   r   is_sslssl_wrap_socketdo_handshake_on_connectdo_handshakeis_http2_negotiatedr   r
   
get_parserr   initiate_connectionr   s    r   initz
TConn.init1   s    		d#;;xx 00DHHE	 xx77II**, ++DII6$(DM"&//$))T[[4#DK KK335 //$((DIIt{{KDK) r   c                 d    t        j                         | j                  j                  z   | _        y N)time	monotonicr   	keepaliver   r&   s    r   set_timeoutzTConn.set_timeoutN   s    ~~'$((*<*<<r   c                 B    t        j                  | j                         y r)   )r   closer   r&   s    r   r/   zTConn.closeR   s    

499r   N)__name__
__module____qualname__r   r'   r-   r/    r   r   r   r   !   s    %L:=r   r   c                   6    e Zd ZdZd Zd Zd Zd Zd Zd	dZ	y)
PollableMethodQueuea  Thread-safe queue that can wake up a selector.

    Uses a pipe to allow worker threads to signal the main thread
    when work is ready, enabling lock-free coordination.

    This approach is compatible with all POSIX systems including
    Linux, macOS, FreeBSD, OpenBSD, and NetBSD. The pipe is set to
    non-blocking mode to prevent worker threads from blocking if
    the pipe buffer fills up under extreme load.
    c                 .    d | _         d | _        d | _        y r)   )_read_fd	_write_fd_queuer&   s    r   r   zPollableMethodQueue.__init__b   s    r   c                     t        j                         \  | _        | _        t        j                  | j                  d       t        j                  | j                  d       t        j                         | _        y)zInitialize the pipe and queue.FN)ospiper7   r8   set_blockingqueueSimpleQueuer9   r&   s    r   r'   zPollableMethodQueue.initg   sL    (*	%t~ 	u-
.'')r   c                     | j                    	 t        j                  | j                          | j                  !	 t        j                  | j                         yy# t        $ r Y 9w xY w# t        $ r Y yw xY w)z Close the pipe file descriptors.N)r7   r;   r/   OSErrorr8   r&   s    r   r/   zPollableMethodQueue.closeq   sn    ==$' >>%( &  
  s"   A A* 	A'&A'*	A65A6c                     | j                   S )z>Return the readable file descriptor for selector registration.)r7   r&   s    r   filenozPollableMethodQueue.fileno~   s    }}r   c                     | j                   j                  t        |g|        	 t        j                  | j
                  d       y# t        $ r Y yw xY w)aD  Queue a callback to be run on the main thread.

        The callback is added to the queue first, then a wake-up byte
        is written to the pipe. If the pipe write fails (buffer full),
        it's safe to ignore because the main thread will eventually
        drain the queue when it reads other wake-up bytes.
            N)r9   putr   r;   writer8   rA   )r   callbackargss      r   deferzPollableMethodQueue.defer   sI     	0401	HHT^^W- 	 	s    A 	AAc                 0   	 t        j                  | j                  |      }d}|t	        |      dz   k  r:	 | j
                  j                         } |        |dz  }|t	        |      dz   k  r9yy# t        $ r Y yw xY w# t        j                  $ r Y yw xY w)zRun queued callbacks. Called when the pipe is readable.

        Drains all available wake-up bytes and runs corresponding callbacks.
        The max_callbacks limit prevents starvation of other event sources.
        Nr   
   r   )	r;   readr7   rA   lenr9   
get_nowaitr>   Empty)r   _fileobjmax_callbacksdatacallbacks_runrH   s         r   run_callbacksz!PollableMethodQueue.run_callbacks   s    	774==-8D c$i"n,;;113
"	 c$i"n,  		 ;; s"    A0 &A? 0	A<;A<?BBN)2   )
r0   r1   r2   __doc__r   r'   r/   rC   rJ   rU   r3   r   r   r5   r5   V   s%    	
* r   r5   c                        e Zd Z fdZed        Z fdZd Zd Z f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 xZS )ThreadWorkerc                 2   t        |   |i | | j                  j                  | _        | j                  j                  | j                  j                  z
  | _        d | _        d | _        t               | _	        t               | _        d| _        d| _        y )Nr   F)superr   r   worker_connectionsthreadsmax_keepalivedtpoolpollerr5   method_queuer   keepalived_connsnr_conns
_accepting)r   rI   kwargs	__class__s      r   r   zThreadWorker.__init__   sy    $)&)"&(("="="hh99DHH<L<LL
/1 %r   c                 ~    |j                   |j                  z
  }|dk  r|j                  r|j                  d       y y y )Nr   z]No keepalived connections can be handled. Check the number of worker connections and threads.)r\   r]   r,   warning)clsr   logr^   s       r   check_configzThreadWorker.check_config   s?    //#++=Q3==KK N O $1r   c                     | j                         | _        t        j                         | _        | j
                  j                          t        | !          y r)   )	get_thread_poolr_   	selectorsDefaultSelectorr`   ra   r'   r[   init_process)r   rf   s    r   rp   zThreadWorker.init_process   s@    ))+
//1 r   c                 V    t        j                  | j                  j                        S )z@Override this method to customize how the thread pool is created)max_workers)r   ThreadPoolExecutorr   r]   r&   s    r   rm   zThreadWorker.get_thread_pool   s    ))dhh6F6FGGr   c                 d    | j                   r$d| _         | j                  j                  d        yy)z)Handle SIGTERM - begin graceful shutdown.Fc                       y r)   r3   r3   r   r   <lambda>z*ThreadWorker.handle_exit.<locals>.<lambda>   s    r   N)alivera   rJ   )r   sigframes      r   handle_exitzThreadWorker.handle_exit   s)    ::DJ##L1 r   c                 ^    | j                   j                  d       t        |   ||       y)z$Handle SIGQUIT - immediate shutdown.FwaitN)r_   shutdownr[   handle_quit)r   rx   ry   rf   s      r   r   zThreadWorker.handle_quit   s'    

'C'r   c                    || j                   k(  ry| j                  D ]f  }|rG|j                  d       | j                  j	                  |t
        j                  | j                         L| j                  j                  |       h || _         y)z,Enable or disable accepting new connections.NF)	rd   socketsr   r`   registerrn   
EVENT_READaccept
unregister)r   enabledlisteners      r   set_accept_enabledzThreadWorker.set_accept_enabled   sp    doo% 	1H$$U+$$Xy/C/CT[[Q&&x0	1 "r   c                 ~      j                   j                   j                        }|j                   fd       y)z0Submit connection to thread pool for processing.c                 R    j                   j                  j                  |       S r)   )ra   rJ   finish_request)futconnr   s    r   rv   z*ThreadWorker.enqueue_req.<locals>.<lambda>   s"    ))//0C0CT3O r   N)r_   submithandleadd_done_callback)r   r   fss   `` r   enqueue_reqzThreadWorker.enqueue_req   s/    ZZt{{D1
O	Qr   c                    	 |j                         \  }}| xj                  dz  c_        |j                  d       t        | j                  |||j                               }| j                  |       y# t        $ rF}|j                  t        j                  t        j                  t        j                  fvr Y d}~yd}~ww xY w)z/Accept a new connection from a listener socket.r   TN)r   rc   r   r   r   getsocknamer   rA   errnoEAGAINECONNABORTEDEWOULDBLOCK)r   r   client_sockclient_addrr   es         r   r   zThreadWorker.accept   s    	'/'8$KMMQM##D);X=Q=Q=STD T" 	wwu||U-?-?ARARSS T	s   A0A3 3	C<<B==Cc                     | j                   j                  |       | j                  j                  |       | j	                  |       y)z0Handle a keepalive connection becoming readable.N)r`   r   rb   remover   )r   r   r   s      r   on_client_socket_readablez&ThreadWorker.on_client_socket_readable   s8    v&$$T* 	r   c                    t        j                         }| j                  r| j                  d   }|j                  |z
  }|dkD  ry| j                  j	                          	 | j
                  j                  |j                         | xj                  dz  c_        |j                          | j                  ryy# t        t        t        f$ r Y Jw xY w)z$Close expired keepalive connections.r   r   N)r*   r+   rb   r   popleftr`   r   r   rA   KeyError
ValueErrorrc   r/   )r   nowr   deltas       r   murder_keepalivedzThreadWorker.murder_keepalived  s    nn##((+DLL3&Eqy !!))+&&tyy1 MMQMJJL ## Xz2 s    %B9 9CCc                     | j                   t        j                         k7  r| j                  j	                  d|        yy)Nz!Parent changed, shutting down: %sFT)ppidr;   getppidrj   infor&   s    r   is_parent_alivezThreadWorker.is_parent_alive  s-    99

$HHMM=tDr   c                     	 | j                   j                  |      }|D ]#  \  }}|j                  } ||j                         % y# t        $ r(}|j
                  t
        j                  k7  r Y d}~yd}~ww xY w)z'Wait for events and dispatch callbacks.N)r`   selectrS   fileobjrA   r   EINTR)r   r   eventskey_rH   r   s          r   wait_for_and_dispatch_eventsz)ThreadWorker.wait_for_and_dispatch_events  sm    	[[''0F  &Q88%&  	ww%++% &	s   AA 	A7A22A7c                 (   | j                   j                  | j                  j                         t        j
                  | j                  j                         | j                  d       | j                  r| j                          | j                  | j                  k  }|| j                  k7  r| j                  |       | j                  d       | j                         sn| j                          | j                  r| j                  d       t!        j"                         | j$                  j&                  z   }| j                  dkD  rYt)        |t!        j"                         z
  d      }|dk(  rn2| j                  |       | j                          | j                  dkD  rY| j*                  j-                  d       | j                   j/                          | j                  j/                          | j0                  D ]  }|j/                           y )NTg      ?)r   Fr   r|   )r`   r   ra   rC   rn   r   rU   r   rw   notifyrc   r\   rd   r   r   r   r*   r+   r   graceful_timeoutmaxr_   r~   r/   r   )r   
can_acceptr   time_remainingss        r   runzThreadWorker.run%  s   T..557&11!..<<	>
 	%jjKKM )@)@@JT__,''
3 --c-:'') ""$! jj& 	&  >>+dhh.G.GGmma !1DNN4D!DaHN"--n-E""$ mma 	

'! 	AGGI	r   c                 :   	 |j                          xr |j                         }|r| j                  r|j                  j	                  d       |j                          | j                  j                  |       | j                  j                  |j                  t        j                  t        | j                  |             y| xj                  dz  c_        |j                          y# t         $ r( | xj                  dz  c_        |j                          Y yw xY w)zHHandle completion of a request (called via method_queue on main thread).Fr   N)	cancelledresultrw   r   r   r-   rb   appendr`   r   rn   r   r   r   rc   r/   	Exception)r   r   r   r,   s       r   r   zThreadWorker.finish_requestT  s    	LLN*:ryy{ITZZ		%%e,  "%%,,T2$$TYY	0D0D%,T-K-KT%RT "

 	MMQMJJL	s   C C) %C) ).DDc                    d}	 |j                   j                  d       |j                          |j                  r| j	                  |      S t        |j                        }|sy| j                  ||      }|r|j                  j                          y	 y# t        j                  j                  $ r&}| j                  j                  d|       Y d}~yd}~wt        $ r&}| j                  j                  d|       Y d}~yd}~wt        j                   $ r}|j"                  d   t        j$                  k(  r6| j                  j                  d       |j                   j'                          nC| j                  j                  d       | j)                  ||j                   |j*                  |       Y d}~yd}~wt,        $ r}|j.                  t.        j0                  t.        j2                  t.        j4                  fvr| j                  j7                  d	       n|j.                  t.        j2                  k(  r| j                  j                  d
       nT|j.                  t.        j4                  k(  r| j                  j                  d       n| j                  j                  d       Y d}~yd}~wt8        $ r2}| j)                  ||j                   |j*                  |       Y d}~yd}~ww xY w)z:Handle a request on a connection. Runs in a worker thread.NTFz*Ignored premature client disconnection. %szClosing connection. %sr   zssl connection closedzError processing SSL request.z Socket error processing request.zIgnoring connection resetzIgnoring socket not connectedzIgnoring connection epipe)r   r   r'   r   handle_http2nextr   handle_requestfinish_bodyr
   errors
NoMoreDatarj   debugStopIterationsslSSLErrorrI   SSL_ERROR_EOFr/   handle_errorr   rA   r   EPIPE
ECONNRESETENOTCONN	exceptionr   )r   r   reqr,   r   s        r   r   zThreadWorker.handlef  s-   0	>
 II!!$' IIK }}((..t{{#C ++C6I '')	 : 1 {{%% 	LHHNNGKK. -  	8HHNN3Q77* ) || 	BvvayC---67		!>?!!#tyy$++qA   		@wwu{{E,<,<ennMM""#EF77e...HHNN#>?WW.HHNN#BCHHNN#>?   	>c499dkk1==	>sV   AB B $.B K'2CK'D  K'BF44K' C$J))K'5(K""K'c           	         |j                   }	 |j                  s| j                  r|j                         }|D ];  }	 | j	                  |||       |j                  |j                  j                         = | j                  s|j                          	 y
|j                  s| j                  ry
# t
        $ rf}| j                  j                  d       	 |j                  |j                  j                  dt        |             n# t
        $ r Y nw xY wY d}~d}~ww xY w# |j                  |j                  j                         w xY w# t        j                  j                   $ r | j                  j#                  d       Y y
t$        j&                  $ rb}|j(                  d   t$        j*                  k(  r| j                  j#                  d       n| j                  j#                  d|       Y d}~y
d}~wt,        $ r`}|j.                  t.        j0                  t.        j2                  t.        j4                  fvr| j                  j                  d       Y d}~y
d}~wt
        $ r | j                  j                  d	       Y y
w xY w)a  Handle an HTTP/2 connection. Runs in a worker thread.

        HTTP/2 connections are persistent and multiplex multiple streams.
        We handle all streams until the connection is closed.

        Returns:
            False (HTTP/2 connections don't use keepalive polling)
        zError handling HTTP/2 requesti  Nz"HTTP/2 connection closed by clientr   zHTTP/2 SSL connection closedzHTTP/2 SSL error: %szHTTP/2 socket errorzHTTP/2 connection errorF)r   	is_closedrw   receive_datahandle_http2_requestr   rj   r   
send_errorstream	stream_idstrcleanup_streamr/   r
   r   r   r   r   r   rI   r   rA   r   r   r   r   )r   r   h2_connrequestsr   r   s         r   r   zThreadWorker.handle_http2  s     ++"	:''DJJ"//1# EC
E11#tWE  ..szz/C/CDE zzMMO G ''DJJF 9 % !**+JK!#..szz/C/CS#a&Q( ! !	!  ..szz/C/CD {{%% 	AHHNN?@  || 	:vvayC---=>5q9   	:wwu{{E,<,<ennMM""#89   	:HH89	:s   -E
 B.AE
 E
 .	D7D0DD	DDDDD DD  'EE
 
8JJAG33J?AI'JJc                    i }d}|j                   j                  	 | j                  j                  | |       t	        j
                         }t        j                  ||j                  |j                  |j                  | j                        \  }}d|d<   d|d<   fd}||d<   g fd}||d	<   | xj                  d
z  c_        | j                  | j                  k\  r.| j                  r"| j                  j                  d       d| _        | j                  ||j                         }	d}
	 t#        |	d      r|	D ]
  }|s|
|z  }
 t#        |	d      r|	j%                          	 rdt'        |j(                        fg}|j*                  D ]/  \  }}|j-                  |j/                         t'        |      f       1 j0                  j3                  |d       j4                     }|j3                  |d       j7                          |
rAj0                  j9                  |
d       |j9                  |
d       j7                          j;                         n(j=                  |j(                  |j*                  |
       t	        j
                         |z
  }| j                  j?                  ||||       	 | j                  jA                  | |||       y# t#        |	d      r|	j%                          w w xY w# tB        $ r | j                  jE                  d       Y yw xY w# 	 | j                  jA                  | |||       w # tB        $ r | j                  jE                  d       Y w w xY wxY w)z&Handle a single HTTP/2 request/stream.NTwsgi.multithread2HTTP_VERSIONc                 ,    j                  d|        y)z!Send 103 Early Hints over HTTP/2.g   N)send_informational)headersr   r   s    r   send_early_hints_h2z>ThreadWorker.handle_http2_request.<locals>.send_early_hints_h2  s    **9c7Cr   zwsgi.early_hintsc                 (    j                  |        y)z.Queue trailers to be sent after response body.N)extend)trailerspending_trailerss    r   send_trailers_h2z;ThreadWorker.handle_http2_request.<locals>.send_trailers_h2  s     ''1r   zgunicorn.http2.send_trailersr   ,Autorestarting worker after current request.Fr   __iter__r/   z:status)
end_streamException in post_request hook)#r   r   r   pre_requestr   r   r   creater   r   r   nrmax_requestsrw   rj   r   start_responsehasattrr/   r   status_coder   r   lowerr   send_headersstreams_send_pending_data	send_datasend_trailerssend_responseaccesspost_requestr   r   )r   r   r   r   environresprequest_startr   r   respiterresponse_bodyitemresponse_headersnamevaluer   request_timer   r   s      `             @@r   r   z!ThreadWorker.handle_http2_request  s6   JJ((	T	EHH  s+$LLNM !KKTYY(,TXX?MD'*.G&'&)GN#D +>G&'  "2 7GG23GGqLGww$+++::HHMM"PQ!&DJ yy$*=*=>H  M%8Z0 ( 2)T1M2 8W-NN$   &/D4D4D0E$F#G #'<< HKD%$++TZZ\3u:,FGH ,,Y8HUZ,[ 3##$4#G**, !OO--iSX-Y$$]u$E..0 %%i1AB %%$$LL!	 $<<>M9LHHOOD#w=E%%dC$?O 8W-NN$ .P  E""#CDEE%%dC$? E""#CDEsa   DL. /K" K" 
E8L. L "LL. $L+*L+.M90MM9$M63M95M66M9c                 r   i }d }	 | j                   j                  | |       t        j                         }t	        j
                  ||j                  |j                  |j                  | j                         \  }}d|d<   | xj                  dz  c_	        | j                  | j                  k\  r>| j                  r"| j                  j                  d       d| _        |j                          | j                  r| j                   j                  s|j                          n2t!        | j"                        | j$                  k\  r|j                          | j	                  ||j&                        }	 t)        ||d         r|j+                  |       n|D ]  }|j-                  |        |j/                          t        j                         |z
  }| j                  j1                  ||||       t3        |d      r|j/                          	 |j5                         r<| j                  j7                  d       	 	 | j                   j9                  | |||       y	 	 | j                   j9                  | |||       y# t        j                         |z
  }| j                  j1                  ||||       t3        |d      r|j/                          w w xY w# t:        $ r | j                  j=                  d	       Y yw xY w# t>        $ r' tA        jB                  tE        jF                           Y t:        $ r |r|jH                  r| j                  j=                  d
       	 |j                  jK                  tL        jN                         |j                  j/                          tQ               # t>        $ r Y tQ               w xY w w xY w# t:        $ r | j                  j=                  d	       Y yw xY w# 	 | j                   j9                  | |||       w # t:        $ r | j                  j=                  d	       Y w w xY wxY w)NTr   r   r   Fzwsgi.file_wrapperr/   zClosing connection.r   zError handling request))r   r   r   r   r   r   r   r   r   r   r   rw   rj   r   force_closer,   rN   rb   r^   r   
isinstance
write_filerG   r/   r   r   should_closer   r   r   r   rA   r   reraisesysexc_infoheaders_sentr~   socket	SHUT_RDWRr   )	r   r   r   r   r   r  r  r  r  s	            r   r   zThreadWorker.handle_request*  sf   7	EHH  s+$LLNM KKTYY(,TXX?MD'*.G&'GGqLGww$+++::HHMM"PQ!&DJ  "::TXX%7%7  "T**+t/B/BB  "yy$*=*=>H%h0C(DEOOH- ( )

4() 

'||~=c7LA8W-NN$  "45"E%%dC$?) #&E%%dC$? ;  (||~=c7LA8W-NN$ .0  E""#CDE%  	*LL#,,.) 	)) ""#;<II&&v'7'78IIOO% $o%  #o% 	  E""#CDEE%%dC$? E""#CDEs   E&K6 -A	I5 6A=K6 5K O+ O 5AK		K6 $K32K36-N>#O+ %1N>AN$
N>$	N9-N>8N99N>>O+ $O('O(+P6-PP6$P30P62P33P6)r0   r1   r2   r   classmethodrk   rp   rm   rz   r   r   r   r   r   r   r   r   r   r   r   r   r   r   __classcell__)rf   s   @r   rY   rY      s{    
  O OH2(
"Q$	-^$5n/bZEx<r   rY   )
concurrentr   r   r;   r>   rn   r  r   r  r*   collectionsr   r   	functoolsr    r   r
   r   r   r   r   r5   WorkerrY   r3   r   r   <module>r     sd      	    
 
         2 2jQ Qh|4;; |r   