abort(): register live socket at urllib3 request() so Force Stop wakes recv() even while waiting for response headers (was only after headers via active_response)

This commit is contained in:
Liang Jiaqing committed 2026-09-14 11:39:06 +08:00
1 parent 96be94586f
commit f07bfc57a2
2 files changed
+9 -5

No files matched your search

+3 -5
View File
@@ -116,12 +116,10 @@ class GenericAgent:
if self.handler is not None: self.handler.code_stop_signal.append(1)
for sess in getattr(self.llmclient.backend, '_sessions', [self.llmclient.backend]):
sess.should_stop = lambda: self.stop_sig # live read; cleared by run()'s finally
try: # wake a recv() blocked in another thread. Verified on Windows: shutdown()/close() do NOT
# wake it (makefile refcount defers real closesocket); _real_close() does -> ChunkedEncodingError
try: # wake a recv() blocked in another thread (waiting headers OR reading stream). Verified on Windows:
# shutdown()/close() do NOT wake it (makefile refcount defers closesocket); _real_close() does
import socket as _socket
raw = sess.active_response.raw
fp = getattr(getattr(raw, '_fp', None), 'fp', None) # http.client response -> buffered socket file
sock = fp.raw._sock if fp else raw.connection.sock # SocketIO._sock (SSL-wrapped OK); fallback urllib3 conn
sock = sys.modules['llmcore']._INFLIGHT[sess._tid] # socket registered at urllib3 request() time, before headers
try: sock.shutdown(_socket.SHUT_RDWR) # for non-Windows semantics
except OSError: pass
try: sock._real_close() # CPython internal; bypasses refcount -> actual closesocket
+6
View File
@@ -1,6 +1,11 @@
import os, json, re, time, requests, sys, threading, urllib3, base64, importlib, uuid, pathlib, copy
from datetime import datetime
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
_INFLIGHT = {} # thread ident -> live socket; lets abort() close it even before response headers arrive
_orig_conn_request = urllib3.connection.HTTPConnection.request
def _conn_request_hook(self, *a, **k): # after request() the socket is connected+sent; conn.sock may later be None'd by http.client
r = _orig_conn_request(self, *a, **k); _INFLIGHT[threading.get_ident()] = self.sock; return r
urllib3.connection.HTTPConnection.request = _conn_request_hook
_RESP_CACHE_KEY = str(uuid.uuid4()); _RESP_CODEX_KEY = str(uuid.uuid4())
_ROOT = os.path.dirname(os.path.abspath(__file__))
if _ROOT not in sys.path: sys.path.append(_ROOT)
@@ -459,6 +464,7 @@ def _stream_with_retry(sess, url, headers, payload, parse_fn):
STATS.update(t_start=time.time(), t_ttft=None)
if not sess.stream: STATS['t_ttft'] = STATS['t_start']
try:
sess._tid = threading.get_ident() # abort() looks up _INFLIGHT[_tid]
with requests.post(url, headers=headers, json=payload, stream=sess.stream,
timeout=(sess.connect_timeout, sess.read_timeout), proxies=sess.proxies, verify=sess.verify) as r:
sess.active_response = r