pcbjam/learning.md
Viktor Vaczi 51b158f6b1 fix(wasm): Fix Asyncify modal errors with global lock mechanism
Update wxwidgets submodule with fix for consecutive modal dialog crashes.
The fix prevents overlapping Asyncify operations that caused "indirect call
to null" and "func is not a function" errors when a second modal was
triggered immediately after the first one completed.

Also includes:
- docs: Clarify build script order and descriptions in CLAUDE.md
- refactor(test): Remove debug logging from wizard test

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 14:35:08 +01:00

1.5 KiB

Learning Notes

Asyncify and Consecutive Modal Dialogs

Problem

When multiple modal dialogs are triggered in quick succession, Asyncify operations can overlap causing crashes:

  • "indirect call to null"
  • "func is not a function"
  • "index out of bounds"

Root Cause

Per Emscripten docs: "It is not safe to start an async operation while another is already running."

When the first modal completes:

  1. Asyncify begins rewinding the C++ stack
  2. C++ code triggers second modal before rewind completes
  3. Second modal's Asyncify operation conflicts with first modal's cleanup
  4. Asyncify state corruption occurs

Key Insight

You cannot use ANY Asyncify mechanism to wait - neither EM_ASYNC_JS await nor emscripten_sleep() - while another Asyncify operation is cleaning up. Both use Asyncify internally and cause the same conflict.

Solution Pattern

  1. Use a global lock to track when Asyncify is busy
  2. Check lock with synchronous JS (EM_JS, not EM_ASYNC_JS) - this doesn't use Asyncify
  3. If locked, return immediately instead of waiting
  4. Release lock via double setTimeout(0) to ensure Asyncify fully completes before allowing new operations
// Good: Synchronous check (no Asyncify)
EM_JS(int, isLocked, (), { return Module._locked ? 1 : 0; });

// Bad: This uses Asyncify and will cause conflicts
while (isLocked()) {
    emscripten_sleep(10);  // Uses Asyncify!
}

File Reference

wxwidgets/src/wasm/dialog.cpp - Modal implementation with lock mechanism