fix: tray restart uses python -m for reliable process respawn
Release / create-release (push) Successful in 1s
Lint & Test / test (push) Successful in 15s
Release / build-linux (push) Successful in 32s
Release / build-windows (push) Successful in 1m8s

The previous os.execv approach and console_script detection both
failed on Windows. Now restart always spawns `python -m media_server.main`
via subprocess.Popen with start_new_session, which works regardless
of how the server was originally started.
This commit is contained in:
2026-03-24 15:26:14 +03:00
parent 32e2ff532d
commit 415231f2f2
2 changed files with 20 additions and 5 deletions
+14
View File
@@ -277,6 +277,20 @@ def main():
# Tray exited — wait for server to finish graceful shutdown # Tray exited — wait for server to finish graceful shutdown
server_thread.join(timeout=10) server_thread.join(timeout=10)
if tray.restart_requested:
import subprocess
# Always restart via `python -m media_server.main` — this works
# regardless of how we were originally started (console_script,
# python -m, or direct script invocation).
cmd = [sys.executable, "-m", "media_server.main"]
subprocess.Popen(
cmd,
cwd=Path.cwd(),
start_new_session=True,
)
else: else:
uvicorn.run( uvicorn.run(
"media_server.main:app", "media_server.main:app",
+6 -5
View File
@@ -3,8 +3,6 @@
import ctypes import ctypes
import io import io
import logging import logging
import os
import sys
import webbrowser import webbrowser
from pathlib import Path from pathlib import Path
from typing import Callable from typing import Callable
@@ -125,10 +123,13 @@ class TrayManager:
if not _confirm("Media Server", "Restart the server?"): if not _confirm("Media Server", "Restart the server?"):
return return
logger.info("Restart requested from tray") logger.info("Restart requested from tray")
self._icon.stop() self._restart_requested = True
self._on_exit() self._on_exit()
os.environ["MEDIA_SERVER_RESTART"] = "1" self._icon.stop()
os.execv(sys.executable, [sys.executable] + sys.argv)
@property
def restart_requested(self) -> bool:
return getattr(self, "_restart_requested", False)
def _shutdown(self, icon: "pystray.Icon", item: "pystray.MenuItem") -> None: def _shutdown(self, icon: "pystray.Icon", item: "pystray.MenuItem") -> None:
if not _confirm("Media Server", "Shut down the server?"): if not _confirm("Media Server", "Shut down the server?"):