mirror of
https://github.com/jamiepine/voicebox.git
synced 2026-09-29 07:05:14 -07:00
Fix keep-server-running on macOS: ignore SIGHUP, watchdog grace period, build script fixes
This commit is contained in:
+16
-1
@@ -58,6 +58,12 @@ def disable_watchdog():
|
||||
"""Disable the parent watchdog so the server keeps running after parent exits."""
|
||||
global _watchdog_disabled
|
||||
_watchdog_disabled = True
|
||||
# Ignore SIGHUP so the server survives when the parent Tauri process exits.
|
||||
# On Unix, child processes receive SIGHUP when the parent's session leader
|
||||
# exits, which would kill the server even though we want it to persist.
|
||||
if sys.platform != "win32":
|
||||
import signal
|
||||
signal.signal(signal.SIGHUP, signal.SIG_IGN)
|
||||
|
||||
|
||||
def _start_parent_watchdog(parent_pid, data_dir=None):
|
||||
@@ -130,7 +136,16 @@ def _start_parent_watchdog(parent_pid, data_dir=None):
|
||||
watchdog_logger.info("Watchdog disabled (keep server running), stopping monitor")
|
||||
return
|
||||
if not _is_pid_alive(parent_pid):
|
||||
watchdog_logger.info(f"Parent process {parent_pid} gone, shutting down server...")
|
||||
# Parent is gone. Before shutting down, give the app a moment
|
||||
# to send /watchdog/disable — there is a race where the Tauri
|
||||
# RunEvent::Exit handler sends the disable request while we are
|
||||
# mid-iteration (already past the _watchdog_disabled check above).
|
||||
watchdog_logger.info(f"Parent process {parent_pid} gone, waiting for possible disable request...")
|
||||
time.sleep(1)
|
||||
if _watchdog_disabled:
|
||||
watchdog_logger.info("Watchdog was disabled during grace period, keeping server alive")
|
||||
return
|
||||
watchdog_logger.info("Watchdog still enabled after grace period, shutting down server...")
|
||||
if sys.platform == "win32":
|
||||
# sys.exit triggers SystemExit, allowing uvicorn to run
|
||||
# shutdown handlers. os.kill(SIGTERM) on Windows calls
|
||||
|
||||
@@ -1,35 +1,34 @@
|
||||
# -*- mode: python ; coding: utf-8 -*-
|
||||
from PyInstaller.utils.hooks import collect_data_files
|
||||
from PyInstaller.utils.hooks import collect_submodules
|
||||
from PyInstaller.utils.hooks import collect_all
|
||||
from PyInstaller.utils.hooks import copy_metadata
|
||||
|
||||
datas = []
|
||||
hiddenimports = ['backend', 'backend.main', 'backend.config', 'backend.database', 'backend.models', 'backend.profiles', 'backend.history', 'backend.tts', 'backend.transcribe', 'backend.platform_detect', 'backend.backends', 'backend.backends.pytorch_backend', 'backend.utils.audio', 'backend.utils.cache', 'backend.utils.progress', 'backend.utils.hf_progress', 'backend.utils.validation', 'torch', 'transformers', 'fastapi', 'uvicorn', 'sqlalchemy', 'librosa', 'soundfile', 'qwen_tts', 'qwen_tts.inference', 'qwen_tts.inference.qwen3_tts_model', 'qwen_tts.inference.qwen3_tts_tokenizer', 'qwen_tts.core', 'qwen_tts.cli', 'pkg_resources.extern', 'backend.backends.mlx_backend', 'mlx', 'mlx.core', 'mlx.nn', 'mlx_audio', 'mlx_audio.tts', 'mlx_audio.stt']
|
||||
binaries = []
|
||||
hiddenimports = ['backend', 'backend.main', 'backend.config', 'backend.database', 'backend.models', 'backend.profiles', 'backend.history', 'backend.tts', 'backend.transcribe', 'backend.platform_detect', 'backend.backends', 'backend.backends.pytorch_backend', 'backend.utils.audio', 'backend.utils.cache', 'backend.utils.progress', 'backend.utils.hf_progress', 'backend.utils.validation', 'backend.cuda_download', 'backend.effects', 'backend.utils.effects', 'backend.versions', 'pedalboard', 'torch', 'transformers', 'fastapi', 'uvicorn', 'sqlalchemy', 'librosa', 'soundfile', 'qwen_tts', 'qwen_tts.inference', 'qwen_tts.inference.qwen3_tts_model', 'qwen_tts.inference.qwen3_tts_tokenizer', 'qwen_tts.core', 'qwen_tts.cli', 'pkg_resources.extern', 'backend.backends.mlx_backend', 'mlx', 'mlx.core', 'mlx.nn', 'mlx_audio', 'mlx_audio.tts', 'mlx_audio.stt']
|
||||
datas += collect_data_files('qwen_tts')
|
||||
# Use collect_all (not collect_data_files) so native .dylib and .metallib
|
||||
# files are bundled as binaries, not data. Without this, MLX raises OSError
|
||||
# when loading Metal shaders inside the PyInstaller bundle.
|
||||
from PyInstaller.utils.hooks import collect_all as _collect_all
|
||||
_mlx_datas, _mlx_bins, _mlx_hidden = _collect_all('mlx')
|
||||
_mlxa_datas, _mlxa_bins, _mlxa_hidden = _collect_all('mlx_audio')
|
||||
datas += _mlx_datas + _mlxa_datas
|
||||
datas += copy_metadata('qwen-tts')
|
||||
hiddenimports += collect_submodules('qwen_tts')
|
||||
hiddenimports += collect_submodules('jaraco')
|
||||
hiddenimports += collect_submodules('mlx')
|
||||
hiddenimports += collect_submodules('mlx_audio')
|
||||
tmp_ret = collect_all('mlx')
|
||||
datas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2]
|
||||
tmp_ret = collect_all('mlx_audio')
|
||||
datas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2]
|
||||
|
||||
|
||||
a = Analysis(
|
||||
['server.py'],
|
||||
pathex=[],
|
||||
binaries=_mlx_bins + _mlxa_bins,
|
||||
binaries=binaries,
|
||||
datas=datas,
|
||||
hiddenimports=hiddenimports,
|
||||
hookspath=[],
|
||||
hooksconfig={},
|
||||
runtime_hooks=[],
|
||||
excludes=[],
|
||||
excludes=['nvidia', 'nvidia.cublas', 'nvidia.cuda_cupti', 'nvidia.cuda_nvrtc', 'nvidia.cuda_runtime', 'nvidia.cudnn', 'nvidia.cufft', 'nvidia.curand', 'nvidia.cusolver', 'nvidia.cusparse', 'nvidia.nccl', 'nvidia.nvjitlink', 'nvidia.nvtx'],
|
||||
noarchive=False,
|
||||
optimize=0,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user