You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

emscripten 1.39.16-fastcomp开启EMTERPRETIFY_ASYNC后longjmp崩溃求解决方案

问题原因

该问题是emscripten 1.39.x fastcomp版本emterpreter-async模式的已知实现缺陷:
emterpreter-async模式下调用emscripten_sleep等异步API时,会在执行栈上保存当前的emterpreter执行状态标记,而默认配置下longjmp执行时不会清理这些异步栈标记。跳转完成后第二次调用emscripten_sleep时,emterpreter会检测到栈上存在异常残留的异步上下文,触发断言失败直接崩溃。

可行规避方案
  • 方案1(最简便):添加-s EMTERPRETIFY_ALLOW_LONGJMP=1编译参数
    该参数是emterpreter专门为适配longjmp跨异步调用栈跳转设计的开关,开启后编译器会自动插入longjmp执行时的异步上下文清理逻辑。修改后的编译命令为:
emcc -O0 -s EMTERPRETIFY=1 -s EMTERPRETIFY_ASYNC=1 -s EMTERPRETIFY_ALLOW_LONGJMP=1 -s WASM=0 c.cpp -o c.js

该方案可以直接解决你给出的最小复现用例的崩溃问题,运行后会正常输出0到10的计数结果。

  • 方案2:调整emterpreter执行白名单
    如果开启上述参数后仍存在崩溃,需要确保所有涉及setjmp/longjmp调用、调用异步API的函数全部由emterpreter执行,避免栈上残留非emterpreter代码的上下文。
    首先通过nm命令查看编译生成的目标文件的符号,获取对应函数的mangled名称,再通过编译参数指定白名单,示例如下:
emcc -O0 -s EMTERPRETIFY=1 -s EMTERPRETIFY_ASYNC=1 -s EMTERPRETIFY_ALLOW_LONGJMP=1 -s EMTERPRETIFY_WHITELIST='["_main", "_Z3runv", "_Z5checkv"]' -s WASM=0 c.cpp -o c.js
  • 方案3:代码层面调整longjmp的触发时机
    如果编译参数调整无法满足需求,可以将longjmp的调用调度到当前异步栈完全退出后执行,避免和当前异步上下文冲突。将用例中longjmp(buffer, 1);修改为:
emscripten_async_call([](void*){ longjmp(buffer, 1); }, nullptr, 0);

该修改会让longjmp在下一个事件循环周期执行,此时之前emscripten_sleep产生的异步栈已经完全清理,不会触发上下文校验失败。


内容的提问来源于stack exchange,提问作者teehessar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.16 12:54:02