Compare commits

...
1 Commits
Author SHA1 Message Date
luciano cdd380d62f 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.
2026-08-02 10:55:47 +02:00
2 changed files with 34 additions and 4 deletions

No files matched your search

+1 -1
View File
@@ -5,7 +5,7 @@ import os
import sys import sys
from pathlib import Path from pathlib import Path
VERSION = "v1.9.0" VERSION = "v1.9.1"
APP_NAME = "MusicTools" APP_NAME = "MusicTools"
+33 -3
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"} 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 # Flag globale per interruzione
_stop_event = threading.Event() _stop_event = threading.Event()
_current_process: Optional[subprocess.Popen] = None _current_process: Optional[subprocess.Popen] = None
@@ -288,17 +292,43 @@ def upgrade_folder(
cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True,
**subprocess_flags(), **subprocess_flags(),
) )
proc = _current_process
for line in _current_process.stdout: # 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(): if is_stopped():
_current_process.terminate() proc.terminate()
return return
pct_match = re.search(r"(\d+(?:\.\d+)?)%", line) pct_match = re.search(r"(\d+(?:\.\d+)?)%", line)
if pct_match and progress_callback: if pct_match and progress_callback:
pct = int(float(pct_match.group(1))) pct = int(float(pct_match.group(1)))
progress_callback(processed, total, filepath.name, "downloading", current_kbps, pct) progress_callback(processed, total, filepath.name, "downloading", current_kbps, pct)
_current_process.wait() try:
proc.wait(timeout=10)
except subprocess.TimeoutExpired:
proc.kill()
try:
proc.wait(timeout=5)
except subprocess.TimeoutExpired:
pass
finally:
watchdog.cancel()
with _process_lock: with _process_lock:
_current_process = None _current_process = None