From 97d35c03d69736cc40ea7ef0b7a3e663f06bd5c8 Mon Sep 17 00:00:00 2001 From: Tw93 Date: Sat, 14 Mar 2026 00:00:08 +0800 Subject: [PATCH] fix(purge): parallelize size calculations to prevent hang (issue #560) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sequential du calls with 15s timeout each meant N artifacts × 15s of potential wait when paths are on slow storage (network mounts, Syncthing, large dirs). Now all du processes are launched concurrently; total time is bounded by the single longest call (≤ 15s) rather than N × 15s. fix(protection): protect CoreAudio paths in should_protect_path (issue #553) Add com.apple.coreaudio*, com.apple.audio.*, and coreaudiod* to the protected path patterns so deep-clean cannot touch audio subsystem caches, reducing risk of audio output loss on Intel Macs running macOS Sequoia. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- lib/clean/project.sh | 26 ++++++++++++++++++++++++-- lib/core/app_protection.sh | 5 +++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/lib/clean/project.sh b/lib/clean/project.sh index c1a9ee7..58b2a29 100644 --- a/lib/clean/project.sh +++ b/lib/clean/project.sh @@ -952,6 +952,24 @@ clean_project_artifacts() { if [[ -t 1 ]]; then start_inline_spinner "Calculating sizes..." fi + + # Pre-compute all sizes in parallel to avoid sequential timeout hangs (issue #560). + # With N artifacts each taking up to 15s, sequential calculation can take N×15s. + # Parallel: all sizes computed concurrently, total ≤ single longest du call. + local -a _size_tmpfiles=() + local -a _size_pids=() + for _sz_item in "${safe_to_clean[@]}"; do + local _stmp + _stmp=$(mktemp) + register_temp_file "$_stmp" + _size_tmpfiles+=("$_stmp") + (get_dir_size_kb "$_sz_item" > "$_stmp" 2> /dev/null) & + _size_pids+=($!) + done + for _spid in "${_size_pids[@]+"${_size_pids[@]}"}"; do + wait "$_spid" 2> /dev/null || true + done + local -a menu_options=() local -a item_paths=() local -a item_sizes=() @@ -1172,16 +1190,20 @@ clean_project_artifacts() { printf "%-*s %9s | %-*s" "$printf_width" "$truncated_path" "$size_str" "$artifact_col" "$artifact_type" } # Build menu options - one line per artifact - # Pass 1: collect data into parallel arrays (needed for pre-scan of widths) + # Pass 1: collect data into parallel arrays (needed for pre-scan of widths). + # Sizes are read from pre-computed results (parallel du calls launched above). local -a raw_project_paths=() local -a raw_artifact_types=() + local _sz_idx=0 for item in "${safe_to_clean[@]}"; do local project_path project_path=$(get_project_path "$item") local artifact_type artifact_type=$(get_artifact_display_name "$item") local size_raw - size_raw=$(get_dir_size_kb "$item") + size_raw=$(cat "${_size_tmpfiles[_sz_idx]}" 2> /dev/null || echo "0") + rm -f "${_size_tmpfiles[_sz_idx]}" 2> /dev/null || true + _sz_idx=$((_sz_idx + 1)) local size_kb=0 local size_human="" local size_unknown=false diff --git a/lib/core/app_protection.sh b/lib/core/app_protection.sh index a37857f..d4c732f 100755 --- a/lib/core/app_protection.sh +++ b/lib/core/app_protection.sh @@ -810,6 +810,11 @@ should_protect_path() { */Library/Mobile\ Documents* | */Mobile\ Documents*) return 0 ;; + # CoreAudio and audio subsystem caches (issue #553) + # Cleaning these can cause audio output loss on Intel Macs + *com.apple.coreaudio* | *com.apple.audio.* | *coreaudiod*) + return 0 + ;; esac # 6. Match full path against protected patterns