From 5b8bce926e1a91ceba8f1d4527a0096fdbc476a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Claude4=CE=9Elope?= Date: Fri, 27 Jun 2025 18:07:15 +0200 Subject: [PATCH] Fix daemon file descriptor handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fixed ValueError with closed file when daemonizing - Properly handle file descriptors with dup2 - Move signal handlers inside async context 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- mcp_browser/daemon_main.py | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/mcp_browser/daemon_main.py b/mcp_browser/daemon_main.py index 893b440..5c77d92 100644 --- a/mcp_browser/daemon_main.py +++ b/mcp_browser/daemon_main.py @@ -35,6 +35,16 @@ async def run_daemon(args): # Create and run daemon daemon = MCPBrowserDaemon(browser, socket_path) + # Set up signal handlers + loop = asyncio.get_event_loop() + + def signal_handler(signum): + logger.info(f"Received signal {signum}") + asyncio.create_task(daemon.stop()) + + for sig in (signal.SIGTERM, signal.SIGINT): + loop.add_signal_handler(sig, signal_handler, sig) + logger.info(f"Starting MCP Browser daemon on {socket_path}") try: @@ -118,20 +128,17 @@ def main(): os.setsid() # Redirect stdin/stdout/stderr - with open(os.devnull, 'r') as devnull: - os.dup2(devnull.fileno(), sys.stdin.fileno()) - with open(os.devnull, 'w') as devnull: - os.dup2(devnull.fileno(), sys.stdout.fileno()) + devnull_in = open(os.devnull, 'r') + devnull_out = open(os.devnull, 'w') + + os.dup2(devnull_in.fileno(), sys.stdin.fileno()) + os.dup2(devnull_out.fileno(), sys.stdout.fileno()) if not args.log_file: - os.dup2(devnull.fileno(), sys.stderr.fileno()) - - # Set up signal handlers - def signal_handler(signum, frame): - logger.info(f"Received signal {signum}") - asyncio.create_task(daemon.stop()) - - signal.signal(signal.SIGTERM, signal_handler) - signal.signal(signal.SIGINT, signal_handler) + os.dup2(devnull_out.fileno(), sys.stderr.fileno()) + + # Close the original file handles after dup2 + devnull_in.close() + devnull_out.close() # Run the daemon asyncio.run(run_daemon(args))