1

I'm copying data to the GraphicBuffer using the following code:

uint8_t *ptr;
sp<GraphicBuffer> gBuffer = new GraphicBuffer(width,height,format,usage);
gBuffer->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&ptr));
//Copy Data
gBuffer->unlock();

EGLClient clientBuffer = (EGLClientBuffer)gBuffer->getNativeBuffer();

EGLImageKHR img = eglCreateImageKHR(eglGetDisplay(EGL_DEFAULT_DISPLAY), EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,clientBuffer, NULL);

glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureHandle);
glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, (GLeglImageOES)img);

//Finished using img, Crash Here:

eglDestroyImageKHR(eglGetDisplay(EGL_DEFAULT_DISPLAY), img);

And the problem comes when calling eglDestroyImageKHR which crashes in some devices and some others not. This is the backtrace:

00 pc 00006488 /system/lib/libui.so
01 pc 00006719 /system/lib/libui.so (android::GraphicBuffer::free_handle()+52)
02 pc 00006813 /system/lib/libui.so (android::GraphicBuffer::~GraphicBuffer()+22)
03 pc 00006841 /system/lib/libui.so (android::GraphicBuffer::~GraphicBuffer()+4)
04 pc 0000f823 /system/lib/libutils.so (android::RefBase::decStrong(void const*) const+40)
05 pc 00003bbb /system/vendor/lib/egl/eglsubAndroid.so
06 pc 0001b5f4 /system/vendor/lib/egl/libEGL_adreno.so (egliDoDestroyEGLImage+80)
07 pc 00006c88 /system/vendor/lib/egl/libEGL_adreno.so (eglDestroyImageKHR+16)
08 pc 0000e749 /system/lib/libEGL.so (eglDestroyImageKHR+44)

Here are a couple of complete backtraces:

http://pastebin.com/S0Ax6eNp

http://pastebin.com/bGWeWruw

Not calling eglDestroyImageKHR causes a leak and when calling again the above routine, gbuffer->lock() fails with an insufficient memory error message.

Crashes for example on a galaxy S4, galaxy s2 , xperia z1 and doesn't crash in a nexus 4, nexus 7, galaxy ace 2...etc

I would appreciate any help.

-EDITED-

The only workaround I have found is to decrease the reference counter to 0 so the GraphicBuffer destructor gets called and frees the memory.

if(gBuffer->getStrongCount() > 0){
    gBuffer->decStrong(gBuffer->handle);
}

2 Answers2

2

I had the same issue with EGL surfaces. Since 4.3 Samsung ROMs don't deactivate the active context and surface when destroying either one. The code now looks something like this:

// This line had to be added to prevent crashes:
mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);

mEgl.eglDestroyContext(mEglDisplay, mEglContext);
mEgl.eglDestroySurface(mEglDisplay, mEglSurface);

The stack trace looked fairly similar. Have you tried destroying gBuffer before calling eglDestroyImageKHR?

Kevin Read
  • 2,173
  • 16
  • 23
  • Hi I can't destroy gbuffer as the destructor it's private in android. The graphicBuffer gets destructed by decrementing the reference count to it via eglImageDestroyKHR. I'll try your solution and see what I get. – Gorilla.Maguila Feb 19 '14 at 20:33
  • Ah, thats annoying. I don't know if the code I copied is of any help here unless you also want to destroy the context (also, its Java, for the C equivalents you'll have to adapt it). Just a wild stab in the dark: Does unbinding the texture before destroying the image help? Does the pointer that was used to copy to the GraphicsBuffer still point to valid memory? Can you paste the whole crash log, especially the registers and the signal that was caught? – Kevin Read Feb 19 '14 at 20:55
  • Yes the ptr and the clientBuffer addresses are still valid. Unbinding does not help at all. The signal is segv_mapper which means if I am not mistaken a null pointer somewhere... I have included a couple of complete logs. Thanks – Gorilla.Maguila Feb 19 '14 at 22:09
  • From the pastebin: `Abort message: '@@@ ABORTING: invalid address or address of corrupt block 0x7a04de88 passed to dlfree'` There's not much to `~GraphicBuffer()`; it doesn't call free() directly in recent sources. Not sure what's causing it to run, or why it's finding a bad address. The numeric value of the address seems reasonable. I ran into similar issues while trying to sort out http://stackoverflow.com/questions/21151259/; haven't had a chance to go back and beat on it some more. – fadden Feb 20 '14 at 01:34
  • I'm beggining to think is a bug in android 4.3 as only crashes in this api. Do you know any method to free the gralloc memory? The thing is that if I dont call egldestroyimage the memory gets filled up in successive calls to the routine. The only workaround is allocate a graphicbuffer only once and reuse it as in here [http://malideveloper.arm.com/downloads/deved/tutorial/SDK/android/egl_image.html](http://malideveloper.arm.com/downloads/deved/tutorial/SDK/android/egl_image.html), but this method fails on tegra 3 devices with a timeout error when locking the buffer. – Gorilla.Maguila Feb 20 '14 at 02:15
  • So you have heap corruption. That was exactly the problem I had with the destruction of the context. Something is freeing up memory and then overwriting the freed up space on the heap, although it has been re-allocated for something else. Is it by design that you run all those without an EGL context? – Kevin Read Feb 20 '14 at 08:52
  • Yes when using oes_image_external you have to use EGL_NO_CONTEXT. [http://software.intel.com/en-us/articles/using-opengl-es-to-accelerate-apps-with-legacy-2d-guis](http://software.intel.com/en-us/articles/using-opengl-es-to-accelerate-apps-with-legacy-2d-guis) and [https://android.googlesource.com/platform/frameworks/native/+/android-4.2.1_r1.1/opengl/tests/gl2_yuvtex/gl2_yuvtex.cpp](https://android.googlesource.com/platform/frameworks/native/+/android-4.2.1_r1.1/opengl/tests/gl2_yuvtex/gl2_yuvtex.cpp) – Gorilla.Maguila Feb 20 '14 at 09:55
  • On http://snorp.net/2011/12/16/android-direct-texture.html they pass attributes to eglCreateImageKHR - maybe that helps? gl2_yuvtex doesn't seem to concern itself with the teardown of the OpenGL state which is where your problem arises, so I don't know if its much help. Does the intel example have the same issue on 4.3? – Kevin Read Feb 20 '14 at 10:06
  • You can safely pass NULL attr to eglCreateImageKHR as the ones in snorp or gl2_yuvtex example are the default attr. Yes in the gl2_yuvtex example are reusing the graphicbuffer, but this method fails on tegra3 devices, so if I fix android 4.3 I screw up tegra 3 :) welcome to android. I have contacted the author of the intel article maybe he knows better. Thanks for your help. – Gorilla.Maguila Feb 20 '14 at 10:17
2

FWIW, in the Mozilla AndroidGraphicBuffer.cpp code, the author writes:

/**
 * XXX: eglDestroyImageKHR crashes sometimes due to refcount badness (I think)
 *
 * If you look at egl.cpp (https://github.com/android/platform_frameworks_base/blob/master/opengl/libagl/egl.cpp#L2002)
 * you can see that eglCreateImageKHR just refs the native buffer, and eglDestroyImageKHR
 * just unrefs it. Somehow the ref count gets messed up and things are already destroyed
 * by the time eglDestroyImageKHR gets called. For now, at least, just not calling      
 * eglDestroyImageKHR should be fine since we do free the GraphicBuffer below.
 *
 * Bug 712716
 */

and essentially does not call eglDestroyImageKHR() which is apparently OK in that context. Bug report here. James Willcox the author of the Mozilla code is also the author of the snorp blog post.

Adi Shavit
  • 16,743
  • 5
  • 67
  • 137