cocos2d / cocos2d-x

Cocos2d-x is a suite of open-source, cross-platform, game-development tools utilized by millions of developers across the globe. Its core has evolved to serve as the foundation for Cocos Creator 1.x & 2.x.
https://www.cocos.com/en/cocos2d-x
18.11k stars 7.05k forks source link

what's wrong with TextureAtlas::drawNumberOfQuads(int, int) #17924

Open toreinkun opened 7 years ago

toreinkun commented 7 years ago

on android, sometimes will cause these error, the crash stack is reported by bugly. i dont't know how to reproduce it.

GLThread 1985(1985)

SIGSEGV(SEGV_MAPERR) 1 #00 pc 00010620 /system/lib/libc.so (__memcpy_base+88) [armeabi-v7a] 2 #01 pc 000fd4e7 /system/vendor/lib/egl/libGLESv2_adreno.so (EsxVertexArrayObject::UpdateInternalVbos(EsxDrawDescriptor const, unsigned int, EsxAttributeDesc const)+1158) [armeabi-v7a] 3 #02 pc 00127ee9 /system/vendor/lib/egl/libGLESv2_adreno.so (A4xVertexArrayObject::CalcVfdRegs(EsxDrawDescriptor const, A4xVfdRegs, int)+932) [armeabi-v7a] 4 #03 pc 0012bf0b /system/vendor/lib/egl/libGLESv2_adreno.so (A4xContext::ValidateVfdState(EsxDrawDescriptor const, int)+38) [armeabi-v7a] 5 #04 pc 00133e3f /system/vendor/lib/egl/libGLESv2_adreno.so (A4xContext::ValidateState(EsxDrawDescriptor const)+1426) [armeabi-v7a] 6 #05 pc 001340dd /system/vendor/lib/egl/libGLESv2_adreno.so (A4xContext::HwValidateGfxState(EsxDrawDescriptor const)+4) [armeabi-v7a] 7 #06 pc 000bd0c3 /system/vendor/lib/egl/libGLESv2_adreno.so (EsxContext::ValidateGfxState(EsxDrawDescriptor const)+486) [armeabi-v7a] 8 #07 pc 000bae75 /system/vendor/lib/egl/libGLESv2_adreno.so (EsxContext::DrawElementsInstanced(EsxPrimType, unsigned int, EsxPixType, void const, unsigned int)+284) [armeabi-v7a] 9 #08 pc 000a93fd /system/vendor/lib/egl/libGLESv2_adreno.so (EsxContext::GlDrawElements(unsigned int, int, unsigned int, void const)+48) [armeabi-v7a] 10 #09 pc 000a0fbf /system/vendor/lib/egl/libGLESv2_adreno.so (glDrawElements+38) [armeabi-v7a] 11 #10 pc 00531ce3 /data/app/com.test.tech/lib/arm/libcocos2dlua.so (cocos2d::TextureAtlas::drawNumberOfQuads(int, int)+318) [armeabi-v7a] 12 #11 pc 004debcd /data/app/com.test.tech/lib/arm/libcocos2dlua.so (cocos2d::Label::onDraw(cocos2d::Mat4 const&, bool)+236) [armeabi-v7a] 13 #12 pc 0052eb9d /data/app/com.test.tech/lib/arm/libcocos2dlua.so (cocos2d::Renderer::visitRenderQueue(cocos2d::RenderQueue&)+252) [armeabi-v7a] 14 #13 pc 0052fb77 /data/app/com.test.tech/lib/arm/libcocos2dlua.so (cocos2d::Renderer::render()+42) [armeabi-v7a] 15 #14 pc 004f5685 /data/app/com.test.tech/lib/arm/libcocos2dlua.so (cocos2d::Scene::render(cocos2d::Renderer*)+204) [armeabi-v7a] 16 #15 pc 00517873 /data/app/com.test.tech/lib/arm/libcocos2dlua.so (cocos2d::Director::drawScene()+110) [armeabi-v7a] 17 #16 pc 0051792b /data/app/com.test.tech/lib/arm/libcocos2dlua.so (cocos2d::Director::mainLoop()+58) [armeabi-v7a] 18 #17 pc 0111538d /data/dalvik-cache/arm/data@app@com.test.tech@base.apk@classes.dex (oatdata+17908621) [armeabi]

dumganhar commented 6 years ago

I also met this issue from bugly report. Could you reproduce this issue?

zhangxu924 commented 6 years ago

We have a lot of this too. It's the top 1 in our crash list. It seems that it is related with app going from background to foreground. It only happens on Devices above Android 7. And the most reported devices are Galaxy J7 and Moto G/ Moto Z.

nauman-tintash commented 6 years ago

Anybody seen if this has been fixed in a later version or not?

waitingchange commented 5 years ago

Hi, We also has many crashes on this . We can only find in OPPO devices ,most of them are OPPO R11 series , including R11 R11S R11T R11ST and R11 PLUS. The version number of android is 7.1.1 ,is there any solution to fix it ?

Ander456 commented 5 years ago

so the problem is not resolved ?? @dumganhar

thinkreed commented 5 years ago

the problem is not resolved。。。we also have some crashes on this

angelvet commented 5 years ago

Hi, 95% of all crashes on my app is this cocos2d::Label::onDraw one! (Cocos2d-x 3.17.1) Are there any clues how this can be fixed? Thanks

minggo commented 5 years ago

Is there any test case to reproduce it? Many things can cause crash in OpenGL ES.

angelvet commented 5 years ago

Nope, sorry. I only have stack-traces from Google Play.

xubing commented 5 years ago

we met this crash also.

stephenhurry commented 5 years ago

@minggo In my case this crash happens when one is trying to purchase IAP and the native purchase dialog shows up

minggo commented 5 years ago

@ichinfungi does it reproduce every time? Which IAP you used? Could you please provide a test case based on cpp-empty-test to reproduce it? Thanks.

stephenhurry commented 5 years ago

@ichinfungi does it reproduce every time? Which IAP you used? Could you please provide a test case based on cpp-empty-test to reproduce it? Thanks.

@minggo sorry I have no time to reproduce it on cap-empty-test now, but I could elaborate the factors:

  1. The crash happened every time when my tester tried to buy an IAP on Android
  2. His testing device is Mi6
  3. I didn't get crash on my own Galaxy S4 and ASUS Zenfone
  4. He was using VPN to execute the aforementioned action in China
  5. The IAP system was developed with SDKBox v2.4.3.3
  6. Previously I have merged PR https://github.com/cocos2d/cocos2d-x/pull/19256 manually, after I undo this, the crash is GONE. Instead an IAP error of code 6 is popped
  7. My conclusion is the crash arises on some Android devices when the app's main activity is paused, in my case, its triggered on the native IAP toast showing up
insama commented 5 years ago

19256 我撤销了这个PR之后就没有再出这种闪退了

minggo commented 5 years ago

@stephenhurry @insama I think the crash is because super.onPause() will release GL context, and there are some queued message in GLSurface's queue. So i think we should invoke super.onPause() like this

public void onPause() {
        this.queueEvent(new Runnable() {
            @Override
            public void run() {
                Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleOnPause();
                (Activity)this.getContext().runOnUiThread(new Runnable(){
                    @Override
                    public void run() {
                        super.onPause();
                    }
                }
            }
        });
        this.setRenderMode(RENDERMODE_WHEN_DIRTY);
    }
stephenhurry commented 5 years ago

@minggo your code can't be compiled

minggo commented 5 years ago

@stephenhurry sorry, the method should be

@Override
    public void onPause() {
        this.queueEvent(new Runnable() {
            @Override
            public void run() {
                Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleOnPause();

                ((Cocos2dxActivity)Cocos2dxGLSurfaceView.this.getContext()).runOnUiThread(new Runnable(){
                    @Override
                    public void run() {
                        Cocos2dxGLSurfaceView.super.onPause();
                    }
                });
            }
        });
        this.setRenderMode(RENDERMODE_WHEN_DIRTY);
        // super.onPause();
    }
sbrednikhin commented 5 years ago

It won't solve problem if some GL calls will be performed while app is paused. IAP is good sample, because it generates some signals that may be handled by app's code when app is paused. In process of handling some label changes i'ts content, and calls FontAtlas::prepareLetterDefinitions, which will call glTexSubImage2D and maybe glGenTextures. After resume app is trying to render label an crushes somewhere inside of GL draw call.

AIGRIND-LLC commented 5 years ago

Hi all. The most common case when the crash occures is when app is in background (Main activity is paused) and any rendering code is called by some system callbacks. For example IAP (Google In-App Billing) or sign-in providers (Google Game Play sign-in) may make such callbacks because all of them show their own activities and pause Main one.

@minggo, we've made a sample based on cpp-empty-test to reproduce the issue with cocos2dx 3.17.2. 👉 cpp-empty-test.zip Only modified files are provided. So extract them to overwrite original ones. Steps to reproduce:

  1. Build and run the app.
  2. Pause it by sending the app to background mode.
  3. Resume the app. It'll cause the crash.

Some details: In AppActivity.java you can find onPause() handler that calls native CallAppPausingEvent() which makes the label to render the text in texture atlas.

    @Override
    protected void onPause() {
        super.onPause();    // failure case
        runOnGLThread(new Runnable() {
            @Override
            public void run() {
                CallAppPausingEvent();
            }
        });
//      super.onPause();    // safe case
    }

There are two super.onPause() calls. One of them must be commented. Depending on which one is called the app will crash or not.

Here is the video attached that show the safe and failure case.

minggo commented 5 years ago

@sbrednikhin engine i think engine will not invoke native codes when it is paused, of course we should invoke super.onPause() after previous queued messages are handled. But engine can not prevent application invoking native codes.

@AIGRIND-LLC i think the safe case may not always safe because CallAppPausingEvent() is invoked asynchronously. It may be invoked after the activity is paused.

minggo commented 5 years ago

@AIGRIND-LLC no matter safe or fail case, it works correctly on my tested device(vivo Y66. I think it is because the opengl es context is not lost. So there is not problem. What device did you test on?

wonyee commented 4 years ago

@AIGRIND-LLC Is there a solution or work around to this issue now?

AIGRIND-LLC commented 4 years ago

@minggo for example the issue can be reproduced on Lenovo TB-8704X. @wonyee there is no common solution yet. Try to comment super.onPause(); in Cocos2dxGLSurfaceView::onPause() in cocos\platform\android\java\src\org\cocos2dx\lib\Cocos2dxGLSurfaceView.java.

hatim-developer commented 4 years ago

I am also getting same bug, is there any solution for this issue.

gitlxrhub commented 1 year ago

@stephenhurry sorry, the method should be

@Override
    public void onPause() {
        this.queueEvent(new Runnable() {
            @Override
            public void run() {
                Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleOnPause();

                ((Cocos2dxActivity)Cocos2dxGLSurfaceView.this.getContext()).runOnUiThread(new Runnable(){
                    @Override
                    public void run() {
                        Cocos2dxGLSurfaceView.super.onPause();
                    }
                });
            }
        });
        this.setRenderMode(RENDERMODE_WHEN_DIRTY);
        // super.onPause();
    }

I solved the above flashback problem with this solution, but it caused new ANR problems, such as:cocos2d::EventDispatcher::resumeEventListenersForTarget(cocos2d::Node*, bool)