Skip to content

[diag] macOS PNG render 33분 hang 원인 검증 — 한글 폰트 부재 가설#20

Open
DanMeon wants to merge 11 commits into
mainfrom
ci/diag-macos-png-hang
Open

[diag] macOS PNG render 33분 hang 원인 검증 — 한글 폰트 부재 가설#20
DanMeon wants to merge 11 commits into
mainfrom
ci/diag-macos-png-hang

Conversation

@DanMeon
Copy link
Copy Markdown
Owner

@DanMeon DanMeon commented May 11, 2026

Summary

test (macos-latest / py3.12) 잡의 단일 테스트 tests/test_render_png.py::TestRenderPng::test_returns_png_magic 가 33분 hang. 로컬 ARM64 macOS 에선 동일 호출이 53.5 ms. 한글 폰트 fallback chain 부재 가설 검증용 임시 PR.

Why

  • 상류 external/rhwp/src/renderer/skia/renderer.rs 의 한글 폰트 fallback chain (Noto Sans KR → ... → Apple SD Gothic Neo → Arial) 에서 시스템 폰트 부재 시 char-by-char fallback 비용이 누적될 가능성
  • GitHub Actions macos-latest runner 의 한글 폰트 보장 여부가 공식 README 에 미명시
  • NanumGothic 설치만으로 정상화되면 가설 확정 → mitigation 패치 채택
  • hang 지속 시 faulthandler thread dump 로 hang 위치 식별

Test plan

  • test (macos-latest / py3.12) 잡이 10분 이내 통과 → 폰트 부재 가설 확정
  • hang 지속 시 5분 timeout + thread dump 로 hang 위치 추적
  • 결과 확인 후 PR close + 브랜치 삭제 (mitigation 채택은 별도 PR)

주의

merge 하지 말 것 — 진단/검증 전용. 진단 commit 은 맨 위 한 개 (32eabb3).
parent 브랜치 ci/schema-publish-skia-deps (0e16f70) 의 publish-schema 변경도 함께 포함됨.

🤖 Generated with Claude Code

DanMeon and others added 11 commits May 11, 2026 10:46
test-other-os (macos-latest / py3.12) 잡이 단일 테스트
test_returns_png_magic 에서 33분 hang 하는 반면 로컬 ARM64 macOS
에선 동일 호출이 53.5 ms 로 끝남. 한글 폰트 fallback chain 부재가
원인이라는 가설을 검증하려고 brew 로 NanumGothic 설치 +
pytest-timeout/faulthandler 로 thread dump 를 받도록 macOS
한정 step 분기. 검증 후 close 예정인 임시 브랜치.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1차 진단에서 NanumGothic 설치에도 동일 hang → 폰트 부재 가설 기각.
Python faulthandler 는 _inner.render_png (PyO3 진입) 직전에서 멈춰
Rust 측 hang 위치를 못 보여줌. macOS sample 명령으로 90 초 wait 후
hung process 의 native frame (Rust + Skia + system call 까지) 을
20 초 sampling. 폰트 인식 확인 (fc-list / system_profiler) 도 함께.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
이전 진단에서 sample 출력에 tail -400 을 걸어 자식 PID 의 Call graph
가 잘려 Binary Images 만 남았음. sample 의 -file 옵션으로 파일에
저장 → Call graph 부분만 awk 로 추출해 stdout 에 노출 + 전체 sample
파일은 actions/upload-artifact 로 업로드해 다운로드 후 분석 가능하게
함.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3차 진단에서 PID 8552 (Python) call graph 가 CoreText
TDownloadableFontManager::Download → libFontRegistryUI →
CFMessagePortSendRequest → mach_msg2_trap 으로 IPC 무한 대기 임을 확인.
원인은 macOS CoreText 의 downloadable-font auto-activation: 시스템에
없는 폰트가 요청되면 FontRegistryUI daemon 에 IPC 로 다운로드 가능성을
물어보고 응답 대기 — Actions runner 환경에서 daemon 이 응답 못 함.

NanumGothic 만으로 효과 없었던 이유는 상류 fallback chain 의 앞쪽
폰트 (Noto Sans KR 등) 가 없어서 거기서부터 다운로드 lookup 발동.
chain 전체 (Noto Sans KR / Noto Serif KR / Noto CJK / Nanum Gothic)
를 설치해 첫 매치에서 lookup 이 끝나도록 함.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
진단 PR 의 macOS 잡 끝에 상류 rhwp 자체 CLI (export-svg) 실행 step
추가. 상류 CLI 도 SkiaRenderer::new 의 FontMgr::default() 진입점을
공유하므로 같은 hang 이 재현되는지 확인. timeout 90s, exit 124 면
hang 으로 판정. PNG path 특이성 vs 상류 전반 영향 구분.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
이전 시도는 working-directory: external/rhwp 에서 target/release/rhwp 를
찾았으나 rhwp-python 의 Cargo.toml 이 workspace 를 정의하고 external/rhwp
를 path dependency 로 포함하므로 cargo build 산출물이 repo root 의
target/ 에 떨어짐. working-directory 제거 + sample 경로를
external/rhwp/samples/aift.hwp 로 보정.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
workspace root 에서 --bin rhwp 빌드 시도가 default-run packages 에서
타깃을 못 찾아 실패함. working-directory: external/rhwp 로 돌려서
cargo 가 그 디렉토리의 [[bin]] 정의를 인식하게 함. 빌드 산출물은
workspace 멤버 발견 결과에 따라 ../../target/release/rhwp 또는
./target/release/rhwp 둘 중 하나로 떨어지므로 양쪽 다 시도.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
이전 시도가 timeout 명령으로 exit 127 (command not found) 종료됨.
GNU coreutils 미포함이라 macOS runner 에 timeout 도 gtimeout 도 없음.
background 실행 + sleep 5s 폴링 + 경과 90s 시 kill -9 패턴으로 직접
구현.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
CTFontManagerSetAutoActivationSetting(null, 1) 호출을
SkiaLayerRenderer::new() 진입 직후에 삽입하는 patch 를 ci/patches/
에 추가. macOS 잡에서 maturin develop --release 직전에 git apply
로 working tree 에만 반영 (external/rhwp 자체 commit 없음). PNG
hang 이 사라지면 후보 B 확정, 그대로면 후보 A 또는 다른 방향
탐색 필요.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
후보 B (CTFontManagerSetAutoActivationSetting) 가 효과 없음을 확인.
검증 에이전트의 회의 — 해당 API 가 타사 font manager activation 알림
용일 뿐 libFontRegistryUI downloadable lookup 은 안 끔 — 이 직접
검증됨.

후보 A 로 교체. font_mgr.family_names() 로 시스템 폰트 family set
을 SkiaLayerRenderer 생성 시 캐시하고, match_family_style 호출 전
에 멤버십 체크해 missing family 는 skip. CoreText 의 downloadable
lookup path 자체에 진입하지 않게 함.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
후보 A patch v2 의 family.as_str() 가 macOS runner 의 Rust 1.95.0
에서 unstable str_as_str feature 로 에러. AsRef::<str>::as_ref(family)
로 변경해 stable 한 표현으로 교정. 로컬 cargo check release OK 확인.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@DanMeon DanMeon force-pushed the ci/diag-macos-png-hang branch from 24648ea to be473ff Compare May 11, 2026 05:07
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