From 607c6dfbab330e904dadd25c286b332fb2c305ce Mon Sep 17 00:00:00 2001 From: CakeCN Date: Wed, 7 Jan 2026 23:52:01 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9C=89=20eventlet.hubs=20=E7=9B=B8=E5=85=B3?= =?UTF-8?q?=E7=9A=84=E9=94=99=E8=AF=AF=E9=83=BD=E4=BC=9A=E8=A2=AB=E6=8D=95?= =?UTF-8?q?=E8=8E=B7=E5=B9=B6=E6=89=93=E5=8D=B0=E8=80=8C=E4=B8=8D=E4=BC=9A?= =?UTF-8?q?=E5=90=91=E5=A4=96=E4=BC=A0=E6=92=AD=E5=AF=BC=E8=87=B4=E6=9C=8D?= =?UTF-8?q?=E5=8A=A1=E5=99=A8=E5=B4=A9=E6=BA=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code-server-like/app/__init__.py | 197 +++++++++++++++---------------- 1 file changed, 97 insertions(+), 100 deletions(-) diff --git a/code-server-like/app/__init__.py b/code-server-like/app/__init__.py index 8578ae2..7a35ea7 100644 --- a/code-server-like/app/__init__.py +++ b/code-server-like/app/__init__.py @@ -8,63 +8,67 @@ logging.getLogger('eventlet.greenio').setLevel(logging.CRITICAL) # 进行猴子补丁操作 eventlet.monkey_patch() -# 配置 eventlet hub 以更优雅地处理 IOClosed 错误 +# 配置 eventlet hub 以更优雅地处理所有错误 try: from eventlet.hubs import hub from eventlet import hubs + import traceback # 保存原始的方法 original_handle_error = hub.Hub.handle_error original_switch = hubs.hub.Hub.switch original_fire_timers = hubs.hub.Hub.fire_timers + original_trampoline = hubs.trampoline def custom_handle_error(self, context, type, value, tb): - # 忽略 IOClosed 错误和相关的 EOFError - error_str = str(value) - if (type.__name__ == 'IOClosed' and 'Operation on closed file' in error_str) or \ - (type.__name__ == 'EOFError') or \ - (type.__name__ == 'OSError' and 'Bad file descriptor' in error_str) or \ - (type.__name__ == 'OSError' and 'Socket operation on non-socket' in error_str): - return - # 其他错误调用原始方法 - original_handle_error(self, context, type, value, tb) + # 捕获并打印所有 eventlet.hubs 相关错误,不再往外raise + print(f"[Eventlet Hub Error] Type: {type.__name__}, Value: {value}") + print(f"[Context] {context}") + print("[Traceback]") + traceback.print_tb(tb) + # 不再调用原始方法,直接返回,不往外传播错误 def custom_switch(self): try: return original_switch(self) except Exception as e: - # 捕获 switch 方法中可能出现的 IOClosed 错误 - error_str = str(e) - if (type(e).__name__ == 'IOClosed' and 'Operation on closed file' in error_str) or \ - (type(e).__name__ == 'EOFError') or \ - (type(e).__name__ == 'OSError' and 'Bad file descriptor' in error_str) or \ - (type(e).__name__ == 'OSError' and 'Socket operation on non-socket' in error_str): - # 优雅处理,返回继续运行 - return None - # 其他异常重新抛出 - raise + # 捕获 switch 方法中所有异常 + print(f"[Eventlet Switch Error] {type(e).__name__}: {e}") + print("[Traceback]") + traceback.print_exc() + # 返回 None 继续运行,不往外传播错误 + return None def custom_fire_timers(self): try: return original_fire_timers(self) except Exception as e: - # 捕获 fire_timers 方法中可能出现的 IOClosed 错误 - error_str = str(e) - if (type(e).__name__ == 'IOClosed' and 'Operation on closed file' in error_str) or \ - (type(e).__name__ == 'EOFError') or \ - (type(e).__name__ == 'OSError' and 'Bad file descriptor' in error_str) or \ - (type(e).__name__ == 'OSError' and 'Socket operation on non-socket' in error_str): - # 优雅处理,记录日志后继续运行 - return - # 其他异常重新抛出 - raise + # 捕获 fire_timers 方法中所有异常 + print(f"[Eventlet Fire Timers Error] {type(e).__name__}: {e}") + print("[Traceback]") + traceback.print_exc() + # 返回继续运行,不往外传播错误 + return + + def custom_trampoline(fd, read=False, write=False, timeout=None, timeout_exc=None): + try: + return original_trampoline(fd, read, write, timeout, timeout_exc) + except Exception as e: + # 捕获 trampoline 方法中所有异常 + print(f"[Eventlet Trampoline Error] {type(e).__name__}: {e}") + print(f"[Params] fd: {fd}, read: {read}, write: {write}, timeout: {timeout}") + print("[Traceback]") + traceback.print_exc() + # 返回 None 继续运行,不往外传播错误 + return None # 替换原始方法 hub.Hub.handle_error = custom_handle_error hubs.hub.Hub.switch = custom_switch hubs.hub.Hub.fire_timers = custom_fire_timers + hubs.trampoline = custom_trampoline - # 同样处理 greenio 模块的所有相关方法 + # 同样处理 greenio 模块的所有相关方法,捕获所有异常 from eventlet import greenio # 保存原始的 greenio 方法 @@ -74,34 +78,20 @@ try: original_send = greenio.base.GreenSocket.send def safe_io_operation(io_func, *args, **kwargs): - """安全执行 IO 操作,处理常见的 IO 错误""" + """安全执行 IO 操作,捕获所有异常""" try: return io_func(*args, **kwargs) except Exception as e: - # 检查是否为需要忽略的 IO 错误 - error_str = str(e) - is_safe_error = False - - # 检查错误类型 - if type(e).__name__ in ('IOClosed', 'EOFError'): - is_safe_error = True - elif type(e).__name__ == 'OSError': - # 检查具体的错误码 - if hasattr(e, 'errno') and e.errno in (9, 88, 107): # Bad file descriptor, Socket operation on non-socket, Operation on closed file - is_safe_error = True - # 检查错误信息 - elif any(msg in error_str for msg in ['Bad file descriptor', 'Socket operation on non-socket', 'Operation on closed file']): - is_safe_error = True - - if is_safe_error: - # 根据操作类型返回适当的默认值 - if 'recv' in io_func.__name__ or 'read' in io_func.__name__: - return b'' if 'recv' in io_func.__name__ else '' - elif 'send' in io_func.__name__ or 'write' in io_func.__name__: - return 0 - return None - # 其他异常重新抛出 - raise + # 捕获所有 IO 操作异常 + print(f"[Eventlet IO Error] {io_func.__name__}: {type(e).__name__}: {e}") + print("[Traceback]") + traceback.print_exc() + # 根据操作类型返回适当的默认值 + if 'recv' in io_func.__name__ or 'read' in io_func.__name__: + return b'' if 'recv' in io_func.__name__ else '' + elif 'send' in io_func.__name__ or 'write' in io_func.__name__: + return 0 + return None def custom_recv_loop(self, recv_func, recv_args, *args, **kwargs): return safe_io_operation(original_recv_loop, self, recv_func, recv_args, *args, **kwargs) @@ -121,7 +111,7 @@ try: greenio.base.GreenSocket._send_loop = custom_send_loop greenio.base.GreenSocket.send = custom_send - # 处理 WSGI 中的错误 + # 处理 WSGI 中的所有错误 try: import eventlet.wsgi original_wsgi_handle_one_request = eventlet.wsgi.HttpProtocol.handle_one_request @@ -131,61 +121,68 @@ try: try: return original_wsgi_handle_one_request(self) except Exception as e: - error_str = str(e) - if (type(e).__name__ == 'IOClosed' and 'Operation on closed file' in error_str) or \ - (type(e).__name__ == 'EOFError') or \ - (hasattr(e, 'errno') and e.errno in (9, 88, 107)): - # 清理连接状态 - try: - self.finish() - except Exception: - pass - return - raise + # 捕获 WSGI 请求处理中的所有异常 + print(f"[Eventlet WSGI Request Error] {type(e).__name__}: {e}") + print("[Traceback]") + traceback.print_exc() + # 清理连接状态并返回,不往外传播错误 + try: + self.finish() + except Exception: + pass + return def custom_wsgi_handle_one_response(self): try: return original_wsgi_handle_one_response(self) except Exception as e: - error_str = str(e) - if (type(e).__name__ == 'IOClosed' and 'Operation on closed file' in error_str) or \ - (type(e).__name__ == 'EOFError') or \ - (hasattr(e, 'errno') and e.errno in (9, 88, 107)): - # 清理连接状态 - try: - self.finish() - except Exception: - pass - return - raise + # 捕获 WSGI 响应处理中的所有异常 + print(f"[Eventlet WSGI Response Error] {type(e).__name__}: {e}") + print("[Traceback]") + traceback.print_exc() + # 清理连接状态并返回,不往外传播错误 + try: + self.finish() + except Exception: + pass + return eventlet.wsgi.HttpProtocol.handle_one_request = custom_wsgi_handle_one_request eventlet.wsgi.HttpProtocol.handle_one_response = custom_wsgi_handle_one_response except Exception as e: # 如果修改失败,忽略错误 - pass + print(f"[WSGI Patch Error] {e}") - # 确保我们捕获所有可能的 IOClosed 错误 - # 修改 eventlet 的全局异常处理 - original_trampoline = hubs.trampoline - - def custom_trampoline(fd, read=False, write=False, timeout=None, timeout_exc=None): - try: - return original_trampoline(fd, read, write, timeout, timeout_exc) - except Exception as e: - error_str = str(e) - if (type(e).__name__ == 'IOClosed' and 'Operation on closed file' in error_str) or \ - (type(e).__name__ == 'EOFError') or \ - (hasattr(e, 'errno') and e.errno in (9, 88, 107)): - # 优雅处理,返回 None - return None - # 其他异常重新抛出 - raise - - hubs.trampoline = custom_trampoline + # 修改 eventlet 所有可能抛出异常的核心方法 + # 遍历 hub.Hub 类的所有方法,包装可能抛出异常的方法 + for method_name in dir(hub.Hub): + if not method_name.startswith('_'): + method = getattr(hub.Hub, method_name) + if callable(method): + def wrap_method(original_method): + def wrapped_method(self, *args, **kwargs): + try: + return original_method(self, *args, **kwargs) + except Exception as e: + print(f"[Eventlet Hub Method Error] {method_name}: {type(e).__name__}: {e}") + print("[Traceback]") + traceback.print_exc() + # 返回适当的默认值 + if method_name == 'add': + return None + elif method_name == 'remove': + return None + return None + return wrapped_method + + # 替换原始方法 + setattr(hub.Hub, method_name, wrap_method(method)) + + print("[Eventlet Error Handling] All eventlet.hubs errors will be caught and printed, not raised") except Exception as e: - # 如果修改失败,忽略错误 - pass + # 如果修改失败,打印错误但继续运行 + print(f"[Eventlet Patch Initialization Error] {e}") + traceback.print_exc() from flask import Flask from .views.routes import main_bp