Skip to content

Comments

fix(tsfn): prevent undefined behavior from user callback exceptions#6

Closed
pproenca wants to merge 3 commits intomasterfrom
fix/tsfn-callback-exception-handling
Closed

fix(tsfn): prevent undefined behavior from user callback exceptions#6
pproenca wants to merge 3 commits intomasterfrom
fix/tsfn-callback-exception-handling

Conversation

@pproenca
Copy link
Owner

@pproenca pproenca commented Jan 4, 2026

Summary

Fixes critical undefined behavior when user-provided callbacks throw exceptions in ThreadSafeFunction contexts.

Changes

  1. TSFN Exception Handling: Wrap all callback invocations in try-catch blocks to prevent exceptions from propagating to the N-API layer

    • AsyncDecodeWorker::ProcessPacket() - error callback
    • AsyncEncodeWorker::EmitChunk() - output callback
    • VideoEncoder::OnOutputTSFN() - output callback
  2. VideoDecoder::Flush Promise Fix: Resolve race condition where promise was moved before enqueue failure could be detected

    • Store deferred promise before enqueue attempt
    • Return correct promise reference on enqueue failure

Why This Matters

Per N-API docs, exceptions thrown in TSFN callbacks cause undefined behavior. This was a critical bug that could crash the Node.js process.

Test Plan

  • Add test for VideoDecoder flush promise rejection
  • Verify no crashes when user callbacks throw
  • Verify existing tests still pass

- Wrap all TSFN callback invocations in try-catch blocks
- Prevents user exceptions from propagating to N-API layer
- Fixes VideoDecoder::Flush promise handling race condition
- Store deferred promise before enqueue to prevent use-after-move
- Add test for flush promise rejection scenario
- Add try/catch blocks around all TSFN callbacks to prevent undefined behavior
- Fix flush promise handling to return same promise instance on early rejection
- Increase cleanup timeout from 100ms to 10s with warning on timeout
- Add comprehensive comments explaining N-API requirements and limitations
- Update test to verify flush() rejects on unconfigured encoder
Implements P0-5 from node-api audit plan to prevent use-after-free during
environment teardown (process.exit, worker termination).

Changes:
- Add src/codec_registry.{h,cc} with immortal globals pattern
- Register/unregister all codecs (Video/Audio Encoder/Decoder)
- Add napi_add_env_cleanup_hook to clear registries before teardown
- Document N-API limitation: cleanup hooks cannot reject promises

N-API Limitation:
napi_add_env_cleanup_hook does NOT provide napi_env parameter, making
promise rejection impossible during abnormal shutdown. This is acceptable
per W3C spec - normal shutdown via close() + await flush() works correctly.

Fixes: P0-2, P0-5 from docs/plans/2025-01-04-node-api-audit.md
Tests: 941/946 passing (no new regressions)
Repository owner deleted a comment from claude bot Jan 4, 2026
Repository owner deleted a comment from claude bot Jan 4, 2026
@pproenca
Copy link
Owner Author

Closing PR as requested

@pproenca pproenca closed this Jan 10, 2026
@pproenca pproenca deleted the fix/tsfn-callback-exception-handling branch January 11, 2026 17:41
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