Skip to content

Session Replay: native SIGSEGV in eglDestroySurface (libEGL_emulation) when SimpleVideoEncoder releases its input surface on the Android emulator #6279

Open

Description

@taziz23

Integration

sentry-android (Session Replay, sentry-android-replay)

Build System

Gradle

AGP Version

9.3.1

Proguard

Disabled (debug build)

Other Error Monitoring Solution

Firebase Crashlytics

Version

8.47.0 (sentry-android-gradle-plugin 6.14.0, sentry-native 0.15.2). The relevant code is unchanged in 8.61.0.

Steps to Reproduce

This is an intermittent race, not a deterministic repro.

  1. Enable Session Replay in session mode (io.sentry.session-replay.session-sample-rate = 1.0), default PIXEL_COPY screenshot strategy, NDK integration enabled.
  2. Run the app on an Android Emulator arm64 image: system-images;android-37.1;google_apis_playstore_ps16k;arm64-v8a (16 KB page size, Android 17, build CP31.260623.012), emulator 37.2.12.0, macOS / Apple Silicon host.
  3. Use the app normally while replay records segments (roughly one every 5 s).

We saw one crash after about 2 minutes (25 replay segments). An earlier 25-minute session (312 segments) did not crash.

Expected Result

Releasing a replay segment's video encoder does not crash the process.

Actual Result

Native crash on hwui's RenderThread while it destroys an EGL window surface. All frames are system/vendor code (no app frames):

SIGSEGV: Segfault (signalhandler, unhandled)

<unknown>                                           /system/lib64/libutils.so
android::RefBase::incStrongRequireStrong            /system/lib64/libutils.so
android::GraphicBuffer::from                        /system/lib64/libui.so
android::Surface::hook_cancelBuffer                 /system/lib64/libgui.so
egl_window_surface_t::~egl_window_surface_t         /vendor/lib64/egl/libEGL_emulation.so
egl_window_surface_t::~egl_window_surface_t         /vendor/lib64/egl/libEGL_emulation.so
eglDestroySurface                                   /vendor/lib64/egl/libEGL_emulation.so
<unknown>                                           /system/lib64/libEGL.so
<unknown> x7                                        /system/lib64/libhwui.so
android::Thread::_threadLoop                        /system/lib64/libutils.so
<unknown>                                           /system/lib64/libutils.so
<unknown> x2                                        /apex/com.android.runtime/lib64/bionic/libc.so

The crash time lines up with the end of the last recorded replay segment: the replay for that session ends in the same second the native crash was captured.

Why we think SimpleVideoEncoder is the source. The libhwui frames are not symbolicated, so this comes from the shape of the stack plus the timing, not a frame-by-frame match:

  • SimpleVideoEncoder.encode() draws each frame with surface.lockHardwareCanvas() on non-Xiaomi/Motorola/Unisoc devices (SimpleVideoEncoder.kt#L201 @ 8.61.0). That gives the MediaCodec input Surface a hwui context, which owns an EGL window surface on the RenderThread.
  • SimpleVideoEncoder.release() calls mediaCodec.release() before surface?.release() (L313-L330 @ 8.61.0). So the hwui context's EGL surface is destroyed after the codec, which is the BufferQueue consumer, has already been released.
  • The emulator's EGL driver keeps a dequeued buffer on its window surface and cancels it in ~egl_window_surface_t. By then the buffer behind it has already been freed, so GraphicBuffer::from → incStrongRequireStrong dereferences a dead object.

The emulator's libEGL_emulation is arguably at fault for touching a freed buffer. But the replay SDK is the code that creates and tears down this surface every few seconds, and only on the emulator does that become a process crash.

Possible fixes

Either of these, or both, would remove the window:

  1. In SimpleVideoEncoder.release(), release the input Surface (which destroys its hwui context and EGL surface) before mediaCodec.release(), after drainCodec(true) / mediaCodec.stop().
  2. Use surface.lockCanvas(null) instead of lockHardwareCanvas() on emulators, as is already done for Xiaomi, Motorola, and Unisoc. For example, check Build.HARDWARE for ranchu or goldfish, or Build.FINGERPRINT starting with generic/google/sdk_gphone.

We can test a patched build on the same emulator image if that helps.

Activity

  1. linear-code commented on Oct 19, 2026

    @linear-code
  2. moved this to Waiting for: Product Owner in GitHub Issues with 👀 3on Oct 19, 2026
  3. romtsn commented on Oct 19, 2026

    @romtsn
    Contributor

    hi, thanks for the detailed analysis and the suggested fix -- I've chosen the 2nd option as this only concerns emulators and it's a less involved fix than the 1st one (it would require testing on more devices which we don't currently own). Once #6282 lands you can try it in the next version of the SDK 👍

  4. moved this from Waiting for: Product Owner to No status in GitHub Issues with 👀 3on Oct 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions