AI Briefing

wasm-bindgen에서 panic과 abort 복구로 Rust Workers를 안정화하기

·2026.04.22 22:00

핵심 내용

panic=unwind와 abort 복구로 Rust Workers의 sandbox poisoning을 막는다.

자세히 보기

Rust Workers는 Rust를 WebAssembly로 컴파일해 Cloudflare Workers에서 실행하지만, panic이나 unexpected abort가 나면 런타임 상태가 오염돼 다른 요청까지 영향을 받을 수 있었다. 핵심 문제는 Rust-to-JavaScript 바인딩을 만드는 wasm-bindgen에 복구 semantics가 없었다는 점이다.

초기 대응은 Worker 내부의 실패 상태를 추적하는 custom Rust panic handler와, 실패 후 전체 애플리케이션을 다시 초기화하는 방식이었다. JavaScript 쪽에서는 Proxy 기반으로 Rust-JavaScript 경계를 감싸 모든 entrypoint를 일관되게 처리했고, 생성된 bindings도 재초기화되도록 수정했다. 이 방식은 workers-rs 0.6부터 기본 적용됐다.

이후 목표는 상태를 버리지 않고 panic을 복구하는 것이었다. 이를 위해 panic=unwind를 WebAssembly Exception Handling 위에서 지원하도록 만들었고, RUSTFLAGS='-Cpanic=unwind' cargo build -Zbuild-std로 표준 라이브러리까지 unwind 지원과 함께 다시 빌드했다. 예외가 발생해도 destructors가 정상 실행되고, std::panic::catch_unwind도 Wasm에서 올바르게 동작하게 됐다.

이 과정에서 wasm-bindgen 툴체인에도 여러 수정이 필요했다.

  • Walrus에 try/catch instruction 파싱 지원 추가
  • exception handling block을 해석하는 descriptor interpreter 개선
  • Rust-JavaScript 경계에서 panic을 잡아 **JavaScript PanicError**로 노출
  • async export는 Promise를 PanicError로 reject
  • extern "C-unwind"로 export를 표시해 경계 너머 unwind를 허용

클로저는 별도 처리가 필요했다. MaybeUnwindSafe라는 새 trait로 panic=unwind일 때만 UnwindSafe를 검사했고, unwind-safe를 보장할 수 없는 경우를 위해 Closure::new_aborting 변형을 추가해 panic 시 unwind 대신 종료하도록 했다.

이렇게 하면 panic이 나도 다음이 보장된다.

  • exported Rust function의 panic은 wasm-bindgen이 포착
  • JavaScript에는 PanicError로 전달
  • async export는 Promise reject 처리
  • Rust destructors 정상 실행
  • WebAssembly instance는 계속 재사용 가능

abort는 여전히 남는다. OOM 같은 경우는 unwind가 불가능하므로 상태 복구 자체는 할 수 없지만, 이후 요청이 잘못된 상태를 물려받지 않도록 abort를 감지하고 격리하는 것이 필요했다. 이를 위해 abort와 unwind를 구분할 수 있게 Exception.Tag를 활용했고, 새 abort hook인 set_on_abort와 reentrancy guard를 더해 잘못된 상태가 다음 호출로 번지지 않게 했다.

이 작업은 wasm-bindgen 라이브러리 사용 사례에도 확장됐다. experimental --reset-state-function을 통해 Wasm 인스턴스를 다시 import/recreate하지 않고도 내부 상태를 초기 상태로 되돌릴 수 있게 했고, old instance의 class handle은 orphaned 되지만 새 class는 계속 만들 수 있다. 즉, 앱이 오류를 겪더라도 완전히 bricked 되지는 않는다.

장기적으로는 Rust의 Wasm 지원을 더 안정화하는 작업도 병행했다. modern WebAssembly Exception Handling은 v8 13.8.1(2025-04-28), workerd v1.20250620.0(2025-06-19), Chrome 138(2025-06-28), Firefox 131(2024-10-01), Safari 18.4(2025-03-31), Node.js 25.0.0(2025-10-15)에서 지원된다. 특히 Node.js 24 LTS 때문에 legacy EH에 묶일 우려가 있었지만, Cloudflare는 이를 backport해 Node.js 24와 22 라인까지 지원하도록 만들었다.

최신 Rust Workers에는 0.8.0부터 --panic-unwind 플래그가 추가됐다. 이 플래그를 쓰면 panic은 더 안전하게 복구되고, abort도 새 분류/복구 훅을 통해 다음 요청에 영향을 주지 않도록 처리된다.

이 한국어 요약은 AI가 자동으로 만들었습니다. 원문의 주장과 맥락은 원문에서 확인해 주세요. 저작권은 원저작자에게 있습니다.

AI 처리 방식을 확인하거나, 요약 오류와 출처 표기 문제, 삭제 요청을 문의 · 건의로 알려주세요.