Skip to content

Can't exit the runtime immediately after emscripten_cancel_main_loop without errors when using assertions #27456

Description

@NoctemCat

Version of emscripten/emsdk:
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 6.0.5 (1db5137)
clang version 24.0.0git (https:/github.com/llvm/llvm-project abd3b3a1445b5a8eeffae5c3912883faa9287fb7)
Target: wasm32-unknown-emscripten
Thread model: posix
InstalledDir: /home/noctemcat/programs/emsdk/upstream/bin

Failing example:

emcmake cmake -S . -B build && cmake --build build
cmake file
cmake_minimum_required(VERSION 3.19)
project(main_loop_exit LANGUAGES CXX)
add_executable(app main.cpp)
set_target_properties(app 
  PROPERTIES 
    CXX_STANDARD 17
    CXX_STANDARD_REQUIRED ON
    CXX_EXTENSIONS OFF
    SUFFIX ".html"
    COMPILE_OPTIONS "-Wall;-Wextra;-O3"
    LINK_OPTIONS "-sEXIT_RUNTIME=1;-sASSERTIONS=2;-O3"
)

Edit: Forgot to test with -O0 when creating the issue, after testing the results are the same as -O3.


Error 1:

Similar pattern is used in test_emscripten_main_loop.c, test_emscripten_main_loop_setimmediate.c, test_emscripten_main_loop_settimeout.c, canvas_animate_resize.c, test_sdl2_mixer_wav.c, emscripten_api_browser.c, webgl_sample_query.c, emscripten_api_browser_infloop.cpp, test_sockets_select_server_closes_connection_client_rw.c, test_emscripten_async_wget2.cpp, test/core/pthread/exceptions.cpp, test_sockets_select_server_down_client.c, webgl_timer_query.c, etc. (I got tired of searching for them). It errored, but I think it exited the runtime after it, not fully sure.

Error:
app.js:1 program exited (with status: 0), but keepRuntimeAlive() is set (counter=1) due to an async operation, so halting execution but not exiting the runtime or preventing further async execution (you can use emscripten_force_exit, if you want to force a true shutdown)

code
void loop() {
    std::cout << "called loop \n";
    emscripten_cancel_main_loop();
    exit(0);
}
int main() {
    emscripten_set_main_loop(&loop, -1, false);
    return 99;
}

Error 2:

Similar pattern is used in main_thread_join.c, test_sdl2_mixer_music.c. I really expected the forced version to work better instead of abort.

app.js:1 Aborted(Assertion failed)
app.js:1 Uncaught RuntimeError: Aborted(Assertion failed)
    at abort (app.js:1:11170)
    at assert (app.js:1:5020)
    at runtimeKeepalivePop (app.js:1:21495)
    at checkIsRunning (app.js:1:21899)
    at MainLoop_runner (app.js:1:23080)
code
void loop() {
    std::cout << "called loop \n";
    emscripten_cancel_main_loop();
    emscripten_force_exit(0);
}
int main() {
    emscripten_set_main_loop(&loop, -1, false);
    return 99;
}

Error 3:

The error text is the same as error 1, but it loops. I kinda missed this possible usage myself, but it was used in webrtc_host.c.

code
void loop() {
    std::cout << "called loop \n";
    exit(0);
    emscripten_cancel_main_loop();
}
int main() {
    emscripten_set_main_loop(&loop, -1, false);
    return 99;
}

Working 1:

code
void loop() {
    std::cout << "called loop \n";
    emscripten_force_exit(0);
}
int main() {
    emscripten_set_main_loop(&loop, -1, false);
    return 99;
}

Working 2:

code
void loop() {
    std::cout << "called loop \n";
    emscripten_cancel_main_loop();
    emscripten_async_call([](void *) { exit(0); }, nullptr, 0)
}
int main() {
    emscripten_set_main_loop(&loop, -1, false);
    return 99;
}

Working 3:

This one is weird, it was used in test_async_mainloop.c and it seems to work fine?

code
void loop() {
    std::cout << "called loop \n";
    emscripten_force_exit(0);
    emscripten_cancel_main_loop();
}
int main() {
    emscripten_set_main_loop(&loop, -1, false);
    return 99;
}

All of the working examples seems to work fine, but I want to know which of them should be preferred.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions