Skip to content

Fix a RETURN trap that aborted sync-upstream.sh under bash 5 - #2

Merged
litkhai merged 1 commit into
masterfrom
fix/return-trap-bash5
Aug 11, 2026
Merged

Fix a RETURN trap that aborted sync-upstream.sh under bash 5#2
litkhai merged 1 commit into
masterfrom
fix/return-trap-bash5

Conversation

@litkhai

@litkhai litkhai commented Aug 11, 2026

Copy link
Copy Markdown
Owner

CI's "generated files are in sync" check failed, but nothing was out of sync — tools/sync-upstream.sh exited 1 after writing every file correctly.

CI 의 "생성 파일 동기화" 검사가 실패했지만 동기화 문제가 아니었습니다. tools/sync-upstream.sh 가 모든 파일을 정상적으로 기록한 뒤 1 로 종료했습니다.

tools/sync-upstream.sh: line 319: tmp: unbound variable

Cause / 원인

local tmp; tmp="$(mktemp -d)"; trap 'rm -rf "$tmp"' RETURN

A RETURN trap set inside a function is not scoped to that function. It stayed armed and fired again on every later function return; on the last one the local it referenced was out of scope and set -u aborted the script — after Done. had already printed, so it looked like a mysterious failure at the very end rather than a cleanup bug.

함수 안에서 설정한 RETURN 트랩은 해당 함수에 국한되지 않습니다. 트랩이 계속 남아 이후 모든 함수 반환에서 실행되었고, 마지막 실행 시점에는 참조하던 지역 변수가 범위를 벗어나 set -u 가 스크립트를 중단시켰습니다. 이미 Done. 이 출력된 뒤였기 때문에 정리 단계의 버그가 아니라 맨 끝의 알 수 없는 실패처럼 보였습니다.

bash 3.2 on macOS tolerates this; bash 5 on Linux does not — so no local run could have caught it. Minimal reproduction:

macOS 의 bash 3.2 는 허용하고 Linux 의 bash 5 는 허용하지 않습니다 — 로컬 실행으로는 잡을 수 없었습니다. 최소 재현:

first()  { local tmp; tmp=$(mktemp -d); trap 'rm -rf "$tmp"' RETURN; }
second() { :; }
main()   { first; second; }
main            # bash 3.2: fine.  bash 5: tmp: unbound variable

Fix / 수정

One script-level scratch directory, cleaned on EXIT.

스크립트 수준의 스크래치 디렉터리 하나를 EXIT 에서 정리합니다.

Verification / 검증

Ran both generators under bash:5 exactly as CI does:

CI 와 동일하게 bash:5 에서 두 생성기를 실행했습니다.

Check Result
tools/sync-upstream.sh all exit 0
tools/derive-ddl.sh all exit 0
git diff -- engines/ empty — byte-identical output

So the generated files were always reproducible; only the exit status was wrong. No engines/ content changes in this PR.

즉 생성 파일은 원래부터 재현 가능했고 종료 코드만 잘못되었습니다. 이 PR 에 engines/ 내용 변경은 없습니다.

🤖 Generated with Claude Code

CI failed the "generated files are in sync" check, but not because
anything was out of sync: the script itself exited 1 after writing every
file correctly.

    tools/sync-upstream.sh: line 319: tmp: unbound variable

import_clickhouse did:

    local tmp; tmp="$(mktemp -d)"; trap 'rm -rf "$tmp"' RETURN

A RETURN trap set inside a function is not scoped to that function, so it
stayed armed and fired again on every later function return. On the last
one the local it referenced was out of scope, and set -u aborted the
script — after "Done." had already printed, which is why it looked like a
mysterious failure at the very end rather than a cleanup bug.

bash 3.2 on macOS tolerates this and bash 5 on Linux does not, so no
local run could have caught it. Minimal reproduction:

    first()  { local tmp; tmp=$(mktemp -d); trap 'rm -rf "$tmp"' RETURN; }
    second() { :; }
    main()   { first; second; }
    main            # bash 3.2: fine.  bash 5: tmp: unbound variable

Replaced with a single script-level scratch directory cleaned on EXIT.
Verified by running both generators under bash:5 exactly as CI does: both
exit 0 and engines/ comes out byte-identical, so the generated files were
always reproducible — only the exit status was wrong.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@litkhai
litkhai merged commit f61469a into master Aug 11, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant