@@ -287,6 +287,8 @@ jobs:
287287 rw_dmg_image_prefix='/src-tauri/target/'
288288 rw_dmg_image_suffix_regex='/bundle/macos/rw\\..*\\.dmg$'
289289 log_file=""
290+ workspace_root="${GITHUB_WORKSPACE:-$(pwd)}"
291+ workspace_root="${workspace_root%/}"
290292
291293 cleanup_log_file() {
292294 if [ -n "${log_file:-}" ]; then
@@ -307,13 +309,11 @@ jobs:
307309 sleep "${detach_sleep_seconds}"
308310 pass=$((pass + 1))
309311 done
312+ echo "WARN: Failed to detach ${target} after ${detach_attempts} attempts" >&2
310313 return 1
311314 }
312315
313316 cleanup_stale_dmg_state() {
314- local workspace_root
315- workspace_root="$(pwd)"
316-
317317 local dmg_mounts
318318 dmg_mounts="$(mount | awk '$3 ~ /^\/Volumes\/dmg\./ { print $3 }' || true)"
319319 if [ -n "${dmg_mounts}" ]; then
@@ -341,7 +341,7 @@ jobs:
341341 next
342342 }
343343 /^=+/ {
344- if (index(image, root image_prefix) > 0 &&
344+ if (index(image, root image_prefix) == 1 &&
345345 image ~ image_suffix_re &&
346346 dev != "") {
347347 print dev
@@ -351,7 +351,7 @@ jobs:
351351 next
352352 }
353353 END {
354- if (index(image, root image_prefix) > 0 &&
354+ if (index(image, root image_prefix) == 1 &&
355355 image ~ image_suffix_re &&
356356 dev != "") {
357357 print dev
@@ -367,13 +367,51 @@ jobs:
367367 done <<< "${workspace_disks}"
368368 fi
369369
370- # Avoid broad process kills; only target likely disk image helper binaries .
370+ # Prefer process IDs linked to this workspace's RW DMG images .
371371 local helper_pids
372- helper_pids="$(
373- pgrep -f '/System/Library/PrivateFrameworks/.*/diskimages-helper' || true
374- pgrep -f '/usr/libexec/diskimages-helper' || true
375- pgrep -f 'diskimages-help' || true
376- )"
372+ helper_pids="$(hdiutil info 2>/dev/null | awk \
373+ -v root="${workspace_root}" \
374+ -v image_prefix="${rw_dmg_image_prefix}" \
375+ -v image_suffix_re="${rw_dmg_image_suffix_regex}" '
376+ BEGIN { image = ""; pid = "" }
377+ /^image-path[[:space:]]*:/ {
378+ line = $0
379+ sub(/^image-path[[:space:]]*:[[:space:]]*/, "", line)
380+ image = line
381+ next
382+ }
383+ /^process ID[[:space:]]*:/ {
384+ line = $0
385+ sub(/^process ID[[:space:]]*:[[:space:]]*/, "", line)
386+ pid = line
387+ next
388+ }
389+ /^=+/ {
390+ if (index(image, root image_prefix) == 1 &&
391+ image ~ image_suffix_re &&
392+ pid ~ /^[0-9]+$/) {
393+ print pid
394+ }
395+ image = ""
396+ pid = ""
397+ next
398+ }
399+ END {
400+ if (index(image, root image_prefix) == 1 &&
401+ image ~ image_suffix_re &&
402+ pid ~ /^[0-9]+$/) {
403+ print pid
404+ }
405+ }
406+ ' | sort -u)"
407+
408+ # Fallback: exact process-name match only, avoid broad -f substring patterns.
409+ if [ -z "${helper_pids}" ]; then
410+ helper_pids="$(
411+ pgrep -x diskimages-helper || true
412+ pgrep -x diskimages-help || true
413+ )"
414+ fi
377415 helper_pids="$(printf '%s\n' "${helper_pids}" | awk 'NF' | sort -u)"
378416 if [ -n "${helper_pids}" ]; then
379417 while IFS= read -r pid; do
0 commit comments