mirror of
https://github.com/tiennm99/serena.git
synced 2026-10-13 08:15:59 +00:00
Use a separate process to call webbrowser open,
redirecting output at the OS level to avoid stdout contamination #257
This commit is contained in:
1 parent
8910b38c02
commit
80a4caf36a
1 file changed
+17
-6
+17
-6
@@ -2,7 +2,7 @@
|
||||
The Serena Model Context Protocol (MCP) Server
|
||||
"""
|
||||
|
||||
import contextlib
|
||||
import multiprocessing
|
||||
import os
|
||||
import platform
|
||||
import sys
|
||||
@@ -273,11 +273,10 @@ class SerenaAgent:
|
||||
Logger.root.addHandler(dashboard_log_handler)
|
||||
self._dashboard_thread, port = SerenaDashboardAPI(dashboard_log_handler, tool_names).run_in_thread()
|
||||
if self.serena_config.web_dashboard_open_on_launch:
|
||||
# open the dashboard URL in the default web browser, making sure to redirect output,
|
||||
# as this can print to stdout (contaminating the MCP server stream)
|
||||
with open(os.devnull, "w") as fnull:
|
||||
with contextlib.redirect_stdout(fnull), contextlib.redirect_stderr(fnull):
|
||||
webbrowser.open(f"http://localhost:{port}/dashboard/index.html")
|
||||
# open the dashboard URL in the default web browser (using a separate process to control
|
||||
# output redirection)
|
||||
process = multiprocessing.Process(target=self._open_dashboard, args=(port,))
|
||||
process.start()
|
||||
|
||||
# log fundamental information
|
||||
log.info(f"Starting Serena server (version={serena_version()}, process id={os.getpid()}, parent process id={os.getppid()})")
|
||||
@@ -326,6 +325,18 @@ class SerenaAgent:
|
||||
"You should now pass either --project <project_name> or --project <project_root>."
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _open_dashboard(port: int) -> None:
|
||||
# Redirect stdout and stderr file descriptors to /dev/null,
|
||||
# making sure that nothing can be written to stdout/stderr, even by subprocesses
|
||||
null_fd = os.open(os.devnull, os.O_WRONLY)
|
||||
os.dup2(null_fd, sys.stdout.fileno())
|
||||
os.dup2(null_fd, sys.stderr.fileno())
|
||||
os.close(null_fd)
|
||||
|
||||
# open the dashboard URL in the default web browser
|
||||
webbrowser.open(f"http://localhost:{port}/dashboard/index.html")
|
||||
|
||||
def get_project_root(self) -> str:
|
||||
"""
|
||||
:return: the root directory of the active project (if any); raises a ValueError if there is no active project
|
||||
|
||||
Reference in new issue
Block a user