From 172617a52393bed1471a27f81a62b89f4cf921e6 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Wed, 18 Jun 2025 14:47:17 +0000 Subject: [PATCH] Fix: Enhance logging for OSError and prevent AttributeError This commit addresses two potential issues related to issue #50: 1. Enhanced `OSError` Logging in `utils.py`: The `printResponse` function in `src-python/utils.py` has been modified to include more robust error handling around the `json.dumps()` call. If an `OSError` (such as `[Errno 22] Invalid argument`) occurs during JSON serialization, the function will now: - Log the full traceback of the OSError. - Log the specific problematic response dictionary that caused the error. - Print a fallback JSON error message to stdout. This change aims to help diagnose the root cause of the `OSError` reported by you by capturing the exact data that triggers it. 2. Prevent `AttributeError` for `.close()` calls: Added checks in `src-python/models/osc/osc.py` and `src-python/models/websocket/websocket_server.py` to ensure that objects are not `None` before their `.close()` or `.cancel()` methods are called. This specifically addresses: - `self.browser.zc.close()` and `self.browser.browser.cancel()` in `osc.py`. - `self._loop.close()` in `websocket_server.py`. These changes prevent potential `AttributeError: 'NoneType' object has no attribute 'close'` errors if these objects are not fully initialized before cleanup. --- src-python/models/osc/osc.py | 12 +++++++---- .../models/websocket/websocket_server.py | 3 ++- src-python/utils.py | 21 ++++++++++++++++--- 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src-python/models/osc/osc.py b/src-python/models/osc/osc.py index ef4e1152..a47f1f8d 100644 --- a/src-python/models/osc/osc.py +++ b/src-python/models/osc/osc.py @@ -90,8 +90,10 @@ class OSCHandler: # エラー発生時にbrowserをリセットして次回再初期化 if self.browser is not None: try: - self.browser.zc.close() - self.browser.browser.cancel() + if hasattr(self.browser, 'zc') and self.browser.zc is not None: + self.browser.zc.close() + if hasattr(self.browser, 'browser') and self.browser.browser is not None: + self.browser.browser.cancel() except Exception: pass self.browser = None @@ -140,8 +142,10 @@ class OSCHandler: # browserがある場合はクリーンアップ if self.browser is not None: try: - self.browser.zc.close() - self.browser.browser.cancel() + if hasattr(self.browser, 'zc') and self.browser.zc is not None: + self.browser.zc.close() + if hasattr(self.browser, 'browser') and self.browser.browser is not None: + self.browser.browser.cancel() except Exception: pass self.browser = None diff --git a/src-python/models/websocket/websocket_server.py b/src-python/models/websocket/websocket_server.py index 34762e55..299e7032 100644 --- a/src-python/models/websocket/websocket_server.py +++ b/src-python/models/websocket/websocket_server.py @@ -138,7 +138,8 @@ class WebSocketServer: finally: # 停止指示が出たらすべての接続を閉じ、イベントループを終了 self._loop.run_until_complete(self._shutdown()) - self._loop.close() + if self._loop is not None: + self._loop.close() async def _shutdown(self): """ diff --git a/src-python/utils.py b/src-python/utils.py index 7bc0997b..2676d591 100644 --- a/src-python/utils.py +++ b/src-python/utils.py @@ -115,9 +115,24 @@ def printResponse(status:int, endpoint:str, result:Any=None) -> None: "endpoint": endpoint, "result": result, } - process_logger.info(response) - response = json.dumps(response) - print(response, flush=True) + process_logger.info(response) # Log the unserialized response + + try: + serialized_response = json.dumps(response) + except OSError as e: + errorLogging() # Log the full traceback of the OSError + process_logger.error(f"Problematic response object before json.dumps: {response}") + process_logger.error(f"OSError during json.dumps: {e}") + # Optionally, print a generic error JSON to stdout if needed, or re-raise + # For now, we'll print a simple error message to stdout as a fallback + error_json = json.dumps({ + "status": 500, + "endpoint": endpoint, + "result": {"error": "Failed to serialize response due to OSError", "details": str(e)} + }) + print(error_json, flush=True) + else: + print(serialized_response, flush=True) error_logger = None def errorLogging() -> None: