fix: watchdog su download upgrader (bump v1.9.1)

Prima: se yt-dlp si bloccava nel download di un video (geo-restricted,
YouTube throttle, rete lenta), il for loop su stdout attendeva
indefinitamente e la tab Upgrade si fermava dopo 2-3 brani.

Ora: threading.Timer da 5 min uccide il subprocess se in scaduta.
Al kill il for esce -> codice trova temp_dir vuota -> marca il brano
"download_error" e prosegue col successivo.
This commit is contained in:
luciano committed 2026-08-02 10:55:47 +02:00
1 parent 2689f686ec
commit cdd380d62f
2 files changed
+40 -10

No files matched your search

+1 -1
View File
@@ -5,7 +5,7 @@ import os
import sys
from pathlib import Path
VERSION = "v1.9.0"
VERSION = "v1.9.1"
APP_NAME = "MusicTools"
+39 -9
View File
@@ -13,6 +13,10 @@ from core.paths import find_ytdlp, find_ffmpeg_dir, find_ffprobe, subprocess_fla
AUDIO_EXTENSIONS = {".mp3", ".m4a", ".wav", ".flac"}
# Timeout massimo per singolo download yt-dlp (secondi). Watchdog kill.
# Serve a evitare hang su video geo-restricted, YouTube throttle o rete lenta.
_DOWNLOAD_TIMEOUT_SEC = 300
# Flag globale per interruzione
_stop_event = threading.Event()
_current_process: Optional[subprocess.Popen] = None
@@ -288,17 +292,43 @@ def upgrade_folder(
cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True,
**subprocess_flags(),
)
proc = _current_process
for line in _current_process.stdout:
if is_stopped():
_current_process.terminate()
return
pct_match = re.search(r"(\d+(?:\.\d+)?)%", line)
if pct_match and progress_callback:
pct = int(float(pct_match.group(1)))
progress_callback(processed, total, filepath.name, "downloading", current_kbps, pct)
# Watchdog: kill del subprocess se supera _DOWNLOAD_TIMEOUT_SEC.
# Previene hang indefinito su video problematici (geo-block,
# YouTube throttle, rete lenta). Alla scadenza il process viene
# terminato -> for line esce -> code path "download_error" naturale.
def _watchdog_kill():
try:
if proc.poll() is None:
proc.terminate()
except Exception:
pass
watchdog = threading.Timer(_DOWNLOAD_TIMEOUT_SEC, _watchdog_kill)
watchdog.daemon = True
watchdog.start()
try:
for line in proc.stdout:
if is_stopped():
proc.terminate()
return
pct_match = re.search(r"(\d+(?:\.\d+)?)%", line)
if pct_match and progress_callback:
pct = int(float(pct_match.group(1)))
progress_callback(processed, total, filepath.name, "downloading", current_kbps, pct)
try:
proc.wait(timeout=10)
except subprocess.TimeoutExpired:
proc.kill()
try:
proc.wait(timeout=5)
except subprocess.TimeoutExpired:
pass
finally:
watchdog.cancel()
_current_process.wait()
with _process_lock:
_current_process = None