Skip to content

Impeller Vulkan: Infinite timeout in vkWaitForFences / acquireNextImageKHR causes ANR on Android when GPU is under pressure #184871

Open

Description

@XyTechWorks

Steps to reproduce

  1. Run a Flutter application on an Android device with Adreno GPU (Impeller/Vulkan backend)
  2. While the Flutter app is in the foreground, trigger GPU pressure through one of:
    • Launch a GPU-intensive game (e.g., cold start of a game that performs heavy shader compilation and texture uploads)
    • Allow DMA-BUF memory leak to accumulate (observed 1.9GB~3.1GB in production)
  3. While GPU is under pressure, switch away from the Flutter app (press Home or switch to another app), triggering Activity.onStop() → onSurfaceDestroyed()
  4. The app ANRs within 5-10 seconds

Expected results

The Flutter engine should gracefully handle GPU pressure during surface teardown. When the GPU cannot complete rendering within a reasonable time, the engine should:

  • Time out the fence wait
  • Abandon the current frame (dropping one frame is acceptable)
  • Free the raster thread to process the teardown task
  • Allow the platform thread to complete the Activity lifecycle without blocking indefinitely

Actual results

The platform (main) thread is blocked indefinitely, causing an ANR (Application Not Responding). The blocking chain:

Platform thread:
  Shell::OnPlatformViewDestroyed()     [shell.cc:1189]
    → latch.Wait()                     // no timeout, waits forever
      → waiting for raster thread to complete teardown

Raster thread (blocked, cannot process teardown):
  KHRSwapchainImplVK::AcquireNextDrawable()
    → KHRFrameSynchronizerVK::WaitForFence()  [khr_swapchain_impl_vk.cc:54]
      → vkWaitForFences(timeout=UINT64_MAX)   // infinite wait on GPU fence

The raster thread is stuck in vkWaitForFences with UINT64_MAX timeout because the GPU cannot signal the fence (due to contention or memory pressure). Since the raster thread never completes the current draw, it never picks up the teardown task from its queue, so the latch is never signaled, and the platform thread blocks forever.

Code sample

Code sample

The issue is in the engine internals, not application code. The problematic code locations:

1. impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_impl_vk.cc:47-58

bool WaitForFence(const vk::Device& device) {
    if (!acquire_fence_pending) {
      return true;
    }
    if (auto result = device.waitForFences(
            *acquire,                             // fence
            true,                                 // wait all
            std::numeric_limits<uint64_t>::max()  // timeout (ns) ← INFINITE
        );
        result != vk::Result::eSuccess) {
      VALIDATION_LOG << "Fence wait failed: " << vk::to_string(result);
      return false;
    }
    // ...
}

2. impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_impl_vk.cc:382-387

// @bug  Non-infinite timeouts are not supported on some older Android
//       devices and the only indication we get is log spam which serves to
//       add confusion. Just use an infinite timeout instead of being
//       defensive.
auto [acq_result, index] = context.GetDevice().acquireNextImageKHR(
    *swapchain_,                           // swapchain
    std::numeric_limits<uint64_t>::max(),  // timeout (ns) ← INFINITE
    *sync->render_ready,                   // signal semaphore
    nullptr                                // fence
);

3. shell/common/shell.cc:1189

// Shell::OnPlatformViewDestroyed()
fml::TaskRunner::RunNowOrPostTask(task_runners_.GetRasterTaskRunner(),
                                  raster_task);
latch.Wait();  // ← no timeout, blocks platform thread forever

Screenshots or Video

Screenshots / Video demonstration

[Upload media here]

Logs

Logs

We observed this ANR pattern across 3 different production logs on Android devices with Adreno GPUs:

Scenario GPU Memory Fence Delay Root Cause
Game cold start (P11U) Normal (~456MB) ~7s GPU command queue saturated by game's shader compilation and texture uploads
Frequent app switching (O8) Elevated (1.9GB) ~68s GPU memory pressure from high DMA-BUF usage
DMA-BUF leak (O8) Leaked (2.2~3.1GB) ~3min GPU memory exhaustion, fence cannot signal

All three cases share the identical blocking chain: vkWaitForFences(UINT64_MAX) on raster thread → platform thread latch.Wait() → ANR.

Note about the existing @bug comment in the code (line 378-381):
The comment states "Non-infinite timeouts are not supported on some older Android devices." This may have been true historically, but the consequence of using infinite timeout is that any GPU issue becomes an unrecoverable ANR. A timeout with graceful frame-drop would be strictly better than an infinite hang.

Flutter Doctor output

Doctor output
Flutter 3.38
Android devices: Qualcomm Adreno GPU (Snapdragon platforms)
Affected devices observed: Xiaomi Mix Filp2  REDMI K90

Activity

  1. puneetkukreja98 commented on Apr 10, 2026

    @puneetkukreja98
    Contributor

    @XyTechWorks Thanks for reporting it.
    Could you please verify if this persists on the latest stable version (3.41.6)?

  2. added
    waiting for responseThe Flutter team cannot make further progress on this issue until the original reporter responds
    and removed
    in triagePresently being triaged by the triage team
    on Apr 10, 2026
  3. XyTechWorks commented on Apr 13, 2026

    @XyTechWorks
    Author

    I cannot use the latest stable, but I see that on the latest master branch, the waitforfenc waiting time in ahb_soapchain_impl_vk.cc is still max, so this problem should still exist, Why is it designed as max here.

  4. removed
    waiting for responseThe Flutter team cannot make further progress on this issue until the original reporter responds
    on Apr 13, 2026
  5. added
    in triagePresently being triaged by the triage team
    engineflutter/engine related. See also e: labels.
    platform-androidAndroid applications specifically
    e: impellerImpeller rendering backend issues and features requests
    and removed
    in triagePresently being triaged by the triage team
    on Apr 13, 2026
  6. gaaclarke commented on Apr 13, 2026

    @gaaclarke
    Member

    The root cause of this may have been addressed by @jason-simmons in #183288

  7. added
    P2Important issues not at the top of the work list
    on Apr 13, 2026
  8. XyTechWorks commented on Apr 14, 2026

    @XyTechWorks
    Author

    I see that khr_swapchain_impl_vk.cc is in this change, so does ahb_swapchain_impl_vk.cc not need to be changed?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important issues not at the top of the work liste: impellerImpeller rendering backend issues and features requestsengineflutter/engine related. See also e: labels.platform-androidAndroid applications specificallyteam-engineOwned by Engine teamtriaged-engineTriaged by Engine team

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions