emscripten_sleep_with_yield() 期间的非 emterpreted 调用

Non-emterpreted calls during emscripten_sleep_with_yield()

我有一个 C 例程通过 Emscripten emterpreter, that calls emscripten_sleep_with_yield() 转译为 Javascript。当它产生时,我想 运行 一些 non-emterpreted 异步回调中的 C 代码。当我尝试时,出现一条错误消息:

"This error happened during an emterpreter-async save or load of the stack. Was there non-emterpreted code on the stack during save (which is unallowed)?"

从抽象意义上讲,我不确定为什么在加载或保存堆栈时调用非 empterpreted 代码会出现问题——它实际上不是 on 要求保留的堆栈。

这个非 emterpreted 代码的动机是更新一些对产生的例程可见的结构。我发现回调中的普通 JavaScript 技术上 可能通过对 emscripten 堆执行 setValue() 来实现影响。但是通过 JavaScript 进行 C 操作是很尴尬的,特别是因为许多例程,如 AllocateUTF8() 在幕后调用 _malloc() ......并且那些有同样的问题。

这是一个说明问题的简单示例。有什么办法解决这个......例如在进行非 emterpreted 调用时将 load/save 状态变量存储在某处,然后将它们放回去??

test.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Plain call during Emterpreter Stack Load</title>
    <script src="test.o.js"></script>
    <script>
      Module.onRuntimeInitialized = function() {
        setTimeout(function () {
          console.log("calling not_emterpreted()");
          _not_emterpreted();
        }, 0);
        _emterpreted_yielder();
        console.log("yielding...");
      }
    </script>
  </head>
  <body></body>
</html>

test.c

#include <stdio.h>
#include <emscripten.h>

EMSCRIPTEN_KEEPALIVE void emterpreted_yielder() {
    while (1) {
        printf("emterpreted_yielder() sleeping...\n");
        emscripten_sleep_with_yield(1000);
    }
}

EMSCRIPTEN_KEEPALIVE void not_emterpreted() {
    printf("Entering not_emterpreted()\n");
}

构建:

emcc test.c -o test.o.js -s EMTERPRETIFY=1 -s EMTERPRETIFY_ASYNC=1 -s EMTERPRETIFY_BLACKLIST="['_not_emterpreted']"

在 html 中注释掉对 not_emterpreted() 的调用将导致它执行人们期望的睡眠循环。就像我说的那样,那时你可以改为将 C 影响作为针对 emterpreter 堆的原始 JavaScript 指令。但是...这不是非 emterpreted emscripten C 吗? :-/

这是 emscripten 中过于保守的错误机制。针对这个问题,现在已经取消了限制:

https://github.com/kripken/emscripten/pull/6822