Skip to content

Potential issue with standard main loop in NDK samples #1094

@SysReset

Description

@SysReset

The main loop used in many Android NDK samples follows this standard structure:

void android_main(android_app* state)
{
    ...

    while (!state->destroyRequested) {
        android_poll_source* source = nullptr;
        int result = ALooper_pollOnce(g_engine.IsReady() ? 0 : -1, nullptr, nullptr, (void**)&source);
        if (result == ALOOPER_POLL_ERROR)
            break;

        if (source != nullptr)
            source->process(state, source);

        // Issue: This code is executed even after state->destroyRequested is set to true
        if (g_engine.IsReady())
            g_engine.DrawFrame();
    }

    ...
}

Issue:
state->destroyRequested is set to true in source->process(state, source) when a "destroy" event occurs. However, the code continues executing after state->destroyRequested is set which can lead to undefined behavior, e.g. accessing released resources.

Potential Fix:

android_poll_source* source;
while (ALooper_pollOnce(g_engine.IsReady() ? 0 : -1, nullptr, nullptr, reinterpret_cast<void**>(&source)) != ALOOPER_POLL_ERROR) {
    if (source != nullptr) {
        source->process(state, source);

        // Exit loop immediately after destroy is requested
        if (state->destroyRequested != 0)
            break;
    }

    if (g_engine.IsReady())
        g_engine.DrawFrame();
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions