fix(3597)(3347): write graphify rebuild lock in parent hook to close ENOTEMPTY race
The hook double-forked the rebuild subprocess and returned before the subprocess wrote .planning/graphs/.rebuild.lock. Callers (notably the feat-3347 test cleanup) waited for the lock to disappear before rm -rf'ing the tmpdir, but an absent lock was ambiguous: it could mean "subprocess finished and trapped lock removal" OR "subprocess hasn't started yet." Under ubuntu CI load the second case won, cleanup raced ahead, and rmSync walked into .planning/graphs while the subprocess was still creating files — surfacing as ENOTEMPTY: directory not empty, rmdir '/tmp/gsd-3347-*/.planning/graphs' on the "dispatches on: git commit -m fix" test. Spawn the rebuild as a regular backgrounded job, capture $!, and write the lock file synchronously in the parent before exit. Lock-presence is now a reliable in-flight signal; the rebuild script's existing trap-on-EXIT rm still owns cleanup. Validated: holodeck (ubuntu docker) 11224 pass / 0 fail. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -134,19 +134,21 @@ HOOK_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
REBUILD_SCRIPT="$HOOK_DIR/lib/gsd-graphify-rebuild.sh"
|
||||
[ -f "$REBUILD_SCRIPT" ] || exit 0
|
||||
|
||||
# Detach the rebuild. Portable double-fork via subshell + disown — works on
|
||||
# macOS (no setsid) and Linux. Redirect all I/O to /dev/null so the hook
|
||||
# returns instantly even if the child keeps stdout/stderr handles open.
|
||||
(
|
||||
bash "$REBUILD_SCRIPT" \
|
||||
"$STATUS_FILE" \
|
||||
"$LOCK_FILE" \
|
||||
"$HEAD_SHA" \
|
||||
"$MS_START" \
|
||||
"$GRAPHIFY_BIN" \
|
||||
</dev/null >/dev/null 2>&1 &
|
||||
disown
|
||||
) &
|
||||
disown
|
||||
# Detach the rebuild. Spawn as a regular background job so we can capture
|
||||
# its PID via $! and write it to the lock file synchronously here in the
|
||||
# parent. This eliminates a startup race where a caller (e.g. test cleanup)
|
||||
# observing an absent lock could not distinguish "subprocess finished" from
|
||||
# "subprocess hasn't started yet." With the lock written before this hook
|
||||
# returns, lock-presence is a reliable in-flight signal.
|
||||
bash "$REBUILD_SCRIPT" \
|
||||
"$STATUS_FILE" \
|
||||
"$LOCK_FILE" \
|
||||
"$HEAD_SHA" \
|
||||
"$MS_START" \
|
||||
"$GRAPHIFY_BIN" \
|
||||
</dev/null >/dev/null 2>&1 &
|
||||
REBUILD_PID=$!
|
||||
echo "$REBUILD_PID" > "$LOCK_FILE"
|
||||
disown "$REBUILD_PID" 2>/dev/null || true
|
||||
|
||||
exit 0
|
||||
|
||||
Reference in New Issue
Block a user