Crash in Nexus 5 with Android 5.0.1

Hi,

I’m testing my game on several Android devices, but only on the Nexus 5 (up to now) with Android 5.0.1 is crashing. The first screen (the menu screen) is showing up, but as soon as the player taps the play button, it crashes with the following message in LogCat:

03-24 13:52:47.859: A/libc(22561): Fatal signal 11 (SIGSEGV), code 2, fault addr 0x3f800028 in tid 22595 (GLThread 50234)

This is the rest of the report from LogCat (the package name is nonisoft.limball):

03-24 13:52:47.961: I/DEBUG(180): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
03-24 13:52:47.961: I/DEBUG(180): Build fingerprint: ‘google/hammerhead/hammerhead:5.0.1/LRX22C/1602158:user/release-keys’
03-24 13:52:47.961: I/DEBUG(180): Revision: ‘11’
03-24 13:52:47.961: I/DEBUG(180): ABI: ‘arm’
03-24 13:52:47.961: I/DEBUG(180): pid: 22561, tid: 22595, name: GLThread 50234 >>> nonisoft.limball <<<
03-24 13:52:47.961: I/DEBUG(180): signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr 0x3f800028
03-24 13:52:47.988: I/DEBUG(180): r0 3f800000 r1 00000000 r2 00000000 r3 00000000
03-24 13:52:47.988: I/DEBUG(180): r4 99e8da00 r5 a30ff3b4 r6 a30ff3b4 r7 a3905b50
03-24 13:52:47.988: I/DEBUG(180): r8 a36394a9 r9 9ac68ef0 sl a390fd44 fp 99e8da00
03-24 13:52:47.988: I/DEBUG(180): ip a36afaf4 sp a30ff3a0 lr a36348ef pc a366f85a cpsr 40000030
03-24 13:52:47.989: I/DEBUG(180): backtrace:
03-24 13:52:47.989: I/DEBUG(180): #00 pc 0012485a /data/app/nonisoft.limball-2/lib/arm/libcocos2dcpp.so (cocos2d::TextureAtlas::removeAllQuads()+1)
03-24 13:52:47.989: I/DEBUG(180): #01 pc 000e98eb /data/app/nonisoft.limball-2/lib/arm/libcocos2dcpp.so (cocos2d::label::alignText()+58)
03-24 13:52:47.989: I/DEBUG(180): #02 pc 000e9f27 /data/app/nonisoft.limball-2/lib/arm/libcocos2dcpp.so (cocos2d::label::updateContent()+114)
03-24 13:52:47.989: I/DEBUG(180): #03 pc 000e8b59 /data/app/nonisoft.limball-2/lib/arm/libcocos2dcpp.so (cocos2d::label::getContentSize() const+28)
03-24 13:52:47.989: I/DEBUG(180): #04 pc 000d95eb /data/app/nonisoft.limball-2/lib/arm/libcocos2dcpp.so (GameManager::init()+698)
03-24 13:52:47.989: I/DEBUG(180): #05 pc 000d7b67 /data/app/nonisoft.limball-2/lib/arm/libcocos2dcpp.so (GameManager::CreateScene()+222)
03-24 13:52:47.989: I/DEBUG(180): #06 pc 000d42b9 /data/app/nonisoft.limball-2/lib/arm/libcocos2dcpp.so (MenuScreen::ToNewGame()+22)
03-24 13:52:47.989: I/DEBUG(180): #07 pc 000ec9cf /data/app/nonisoft.limball-2/lib/arm/libcocos2dcpp.so (cocos2d::MenuItem::activate()+26)
03-24 13:52:47.989: I/DEBUG(180): #08 pc 000d46d5 /data/app/nonisoft.limball-2/lib/arm/libcocos2dcpp.so
03-24 13:52:47.989: I/DEBUG(180): #09 pc 001127c9 /data/app/nonisoft.limball-2/lib/arm/libcocos2dcpp.so
03-24 13:52:47.989: I/DEBUG(180): #10 pc 00110619 /data/app/nonisoft.limball-2/lib/arm/libcocos2dcpp.so (cocos2d::EventDispatcher::dispatchEventToListeners(cocos2d::EventDispatcher::EventListenerVector*, std::function<bool (cocos2d::EventListener*)> const&)+172)
03-24 13:52:47.989: I/DEBUG(180): #11 pc 00112d0f /data/app/nonisoft.limball-2/lib/arm/libcocos2dcpp.so (cocos2d::EventDispatcher::dispatchTouchEvent(cocos2d::EventTouch*)+290)
03-24 13:52:47.989: I/DEBUG(180): #12 pc 00112def /data/app/nonisoft.limball-2/lib/arm/libcocos2dcpp.so (cocos2d::EventDispatcher::dispatchEvent(cocos2d::Event*)+50)
03-24 13:52:47.989: I/DEBUG(180): #13 pc 001017b7 /data/app/nonisoft.limball-2/lib/arm/libcocos2dcpp.so (cocos2d::GLView::handleTouchesOfEndOrCancel(cocos2d::EventTouch::EventCode, int, int*, float*, float*)+478)
03-24 13:52:47.989: I/DEBUG(180): #14 pc 00101803 /data/app/nonisoft.limball-2/lib/arm/libcocos2dcpp.so (cocos2d::GLView::handleTouchesEnd(int, int*, float*, float*)+18)
03-24 13:52:47.989: I/DEBUG(180): #15 pc 000df963 /data/app/nonisoft.limball-2/lib/arm/libcocos2dcpp.so (Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeTouchesEnd+34)
03-24 13:52:47.989: I/DEBUG(180): #16 pc 00130ff7 /data/dalvik-cache/arm/data@app@nonisoft.limball-2@base.apk@classes.dex
03-24 13:52:48.900: W/debuggerd(180): type=1400 audit(0.0:334): avc: denied { read } for name=“kgsl-3d0” dev=“tmpfs” ino=6028 scontext=u:r:debuggerd:s0 tcontext=u:object_r:gpu_device:s0 tclass=chr_file
03-24 13:52:48.900: W/debuggerd(180): type=1400 audit(0.0:335): avc: denied { read } for name=“kgsl-3d0” dev=“tmpfs” ino=6028 scontext=u:r:debuggerd:s0 tcontext=u:object_r:gpu_device:s0 tclass=chr_file
03-24 13:52:49.320: W/debuggerd(180): type=1400 audit(0.0:336): avc: denied { read } for name=“kgsl-3d0” dev=“tmpfs” ino=6028 scontext=u:r:debuggerd:s0 tcontext=u:object_r:gpu_device:s0 tclass=chr_file
03-24 13:52:49.320: W/debuggerd(180): type=1400 audit(0.0:337): avc: denied { read } for name=“kgsl-3d0” dev=“tmpfs” ino=6028 scontext=u:r:debuggerd:s0 tcontext=u:object_r:gpu_device:s0 tclass=chr_file
03-24 13:52:49.358: W/ActivityManager(2009): Force finishing activity nonisoft.limball/org.cocos2dx.cpp.AppActivity
03-24 13:52:49.360: I/DEBUG(180): Tombstone written to: /data/tombstones/tombstone_08
03-24 13:52:49.360: I/BootReceiver(2009): Copying /data/tombstones/tombstone_08 to DropBox (SYSTEM_TOMBSTONE)
03-24 13:52:49.361: E/SharedPreferencesImpl(2009): Couldn’t create directory for SharedPreferences file shared_prefs/log_files.xml

In the last line, there is a reference to SharedPreferences error. I use cocos2d::UserDefault to retrieve and save the current best score (and I figure that under the hood, this uses SharedPreferences). As I mentioned, it’s working in all the rest of devices I tested.

If you think this is the problem, any hints on how to fix it? Can you think of another problem (from the LogCat report) that I may be overlooking?

Thanks in advance.

It actually looks like the crash occurred before SharedPrefs, but it could be related still. The stack trace is hard to determine whether it’s the culprit or not, but it reads that when something is touched a label is getting destroyed. Can you show the code how you setup the play button, as well as the action that is called on activate.

Edit: if it only occurs on one device it is likely something on the android/java side of things? But may also be a OpenGL issue. Unless you’ve figured out how to debug the native code with gdb you may need to do some excess logging to figure it out unless someone has a similar issue.

Also, a good test to rule out your code is to create a new project, throw your menu code in the new project and see if it runs fine.

Are your other devices also Android 5.x? If not it could be an NDK/target-build related issue.

Thanks both for your answers.

I tested on a Moto G with Android 5.0.1 and it works well, so I guess that it’s not an NDK/target-build issue. It’s true that I set the APP_PLATFORM in Application.mk to android-19, but I do this because of what I read here and here: if I set APP_PLATFORM to android-21, given that some functions from stdlib.h changed (inline issues), the game wouldn’t run android versions below 5. However, according to those links, setting APP_PLATFORM to android-19 should allow executing the game on Android 5 and below. (I’m using NDK r10d x86_64, which I assume to have the same problem as NDK r10c).

I’m almost sure that there shouldn’t be a problem with the play button code, which it’s pretty standard. In the init method:

mPlayButton = MenuItemImage::create("playMenu.png", "playMenu.png",     CC_CALLBACK_0(MenuScreen::ToNewGame, this));
mPlayButton -> setPosition(Point(origin.x + visibleSize.width / 2, origin.y + visibleSize.height / 2));
this -> addChild(mPlayButton);

The listener:

 listener -> onTouchEnded = [=](Touch* touch, Event* event)  {
    
    Vec2 location = touch -> getLocation();
    if ( mPlayButton -> getBoundingBox().containsPoint(location) )
    {
        mPlayButton -> activate();
    }

And finally, the selector:

void MenuScreen::ToNewGame()
{
    if ( !ConfigManager::GetInstance() -> NoAdsPurchased() )
    {
#if CC_TARGET_PLATFORM == CC_PLATFORM_IOS
        AdBannerC::GetInstance() -> hideBannerView();
#elif CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
        AdmobHelper::HideAd();
#endif
    }
Director::getInstance() -> replaceScene(TransitionCrossFade::create(1.0f, GameManager::CreateScene()));
}

The only “weird” code here is that depending on the system (Android or iOS), I use one or another way to hide the advertisement banner during the main game, but this is also pretty tested and it seems to work fine. In Android, the AdmobHelper is simply an utility class that under the hood calls a static Java method through JNI, which in turn hides the banner (running the action on the UI thread). I debugged and tested this, and it works fine.

I forgot to explain in my first post that the game also crashes when the player, instead of tapping the play button, taps the credits button (which leads to another screen where the credits information is shown). So, it seems that the problem arises when a screen transition/change is taking place. In the case of the credits screen selector, I simply call replaceScene; I don’t do anything about the banner (the credits screen should display the ad banner as well).

EDIT: I’m going to check the labels, because as you pointed out, there might be a hidden problem there. Up to now, this is what I have concerning labels in the init() method of GameManager (which seems to be the point of interruption):

std::stringstream ss1;
ss1 << points;
std::string totalPoints( LocalizationManager::GetInstance() -> getLocalizedString( "Total" ) + ": " + ss1.str());
totalPointsLabel = Label::createWithTTF(totalPoints, "fonts/GILSANUB.TTF", ConfigManager::GetInstance() -> GetFontSizeForPoints() );
totalPointsLabel -> setPosition(Vec2(origin.x + visibleSize.width / 2,
                                      origin.y + visibleSize.height - totalPointsLabel->getContentSize().height));
this->addChild(totalPointsLabel, 1);

std::stringstream ss2;
ss2 << best;
std::string bestPoints( LocalizationManager::GetInstance() -> getLocalizedString( "Best" ) + ": " + ss2.str());
bestPointsLabel = Label::createWithTTF(bestPoints, "fonts/GILSANUB.TTF", ConfigManager::GetInstance() -> GetFontSizeForPoints() );
bestPointsLabel -> setPosition(Vec2(origin.x + visibleSize.width / 2, origin.y + visibleSize.height - totalPointsLabel -> getContentSize().height * 2));
this->addChild(bestPointsLabel, 1);

std::stringstream ss3;
ss3 << lives;
std::string totalLives("x" + ss3.str());
livesLabel = Label::createWithTTF(totalLives, "fonts/GILSANUB.TTF", ConfigManager::GetInstance() -> GetFontSizeForPoints() );
livesLabel -> setPosition(Vec2(origin.x + visibleSize.width - livesLabel -> getContentSize().width / 2,
                                origin.y + visibleSize.height - livesLabel -> getContentSize().height));
this -> addChild(livesSprite);

Variables “lives” and “points” are initialized just right before:

lives = totalLives; //totalLives being a static const defined in the header
points = 0;

“best”, on the other hand, is retrieved from cocos2d::UserDefault:

best =  cocos2d::UserDefault::getInstance() -> getIntegerForKey( "best" );

The thing is that I declare “best” as uint64_t, but getIntegerForKey returns an int, so maybe the error is there. I’ll test it by simply changing the definition of best to best = 0.

Well, I’ve been testing more and the problem persists, but I think I have more clues now. This is the situation,

At first, I thought that the problem may reside in some label, and in concrete, the getContentSize() function of the label (as suggested by the LogCat I posted), so I used CCLog to determine the first point of interruption.

CCLog("total points label");
std::stringstream ss1;
ss1 << points;
std::string totalPoints( LocalizationManager::GetInstance() -> getLocalizedString( "Total" ) + ": " + ss1.str());
totalPointsLabel = Label::createWithTTF(totalPoints, "fonts/GILSANUB.TTF", ConfigManager::GetInstance() -> GetFontSizeForPoints() );
totalPointsLabel -> setPosition(Vec2(origin.x + visibleSize.width / 2,
                                      origin.y + visibleSize.height - totalPointsLabel->getContentSize().height));
this->addChild(totalPointsLabel, 1);

CCLog("best label");
std::stringstream ss2;
ss2 << best;
std::string bestPoints( LocalizationManager::GetInstance() -> getLocalizedString( "Best" ) + ": " + ss2.str());
bestPointsLabel = Label::createWithTTF(bestPoints, "fonts/GILSANUB.TTF", ConfigManager::GetInstance() -> GetFontSizeForPoints() );
bestPointsLabel -> setPosition(Vec2(origin.x + visibleSize.width / 2, origin.y + visibleSize.height - totalPointsLabel -> getContentSize().height * 2));
this->addChild(bestPointsLabel, 1);

After running, only “total points label” was written in the log before the crash, so I assumed that maybe if I commented out the totalPointsLabel -> setPosition function (which calls getContentSize()), the flow would continue… and it did! This time, the log would show: “total points label” and “best label”, but nothing else before the crash. Then, I noticed that bestLabel also used totalPointsLabel -> getContentSize(), so I commented this out. This time, the flow continued until the end of the init() method (there were no more uses of totalPointsLabel in the rest of init()), and then, the crash again.

In the end of init(), I schedule a custom update selector that in turn calls a method that updates the points label, where again getContentSize() is used. This is why I’m starting to conclude that the problem arises with this particular label, maybe during its creation, or maybe due to some problem with getContentSize().

I didn’t have time to perform more tests (I’m using a real device and have limited access to it), but maybe if I remove the getContentSize() calls from the method that is called by my update(), the crash would disappear. I’ll let you know when I can test it.

But for now, anyone has experienced a similar issue? Where do you think the problem might be? Should I use getBoundingBox() to determine size instead of getContentSize()?

Ok, so I tried removing all the labels but the error persists. This is the last LogCat report I got:

03-26 16:03:51.299: I/DEBUG(180): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
03-26 16:03:51.300: I/DEBUG(180): Build fingerprint: ‘google/hammerhead/hammerhead:5.0.1/LRX22C/1602158:user/release-keys’
03-26 16:03:51.300: I/DEBUG(180): Revision: ‘11’
03-26 16:03:51.300: I/DEBUG(180): ABI: ‘arm’
03-26 16:03:51.300: I/DEBUG(180): pid: 1724, tid: 1756, name: GLThread 81004 >>> nonisoft.limball <<<
03-26 16:03:51.300: I/DEBUG(180): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x3f4
03-26 16:03:51.327: I/DEBUG(180): r0 a2c473a0 r1 00000000 r2 a2c6b000 r3 a2cc0fc0
03-26 16:03:51.327: I/DEBUG(180): r4 9a872760 r5 00000001 r6 00000000 r7 a2ca8600
03-26 16:03:51.327: I/DEBUG(180): r8 ab9b6d80 r9 00000024 sl a2eff810 fp 00000000
03-26 16:03:51.327: I/DEBUG(180): ip 00008d66 sp a2eff1e0 lr ab92a959 pc ab956ddc cpsr 000f0030
03-26 16:03:51.327: I/DEBUG(180): backtrace:
03-26 16:03:51.327: I/DEBUG(180): #00 pc 000aeddc /system/vendor/lib/egl/libGLESv2_adreno.so (oxili_load_sampler+51)
03-26 16:03:51.327: I/DEBUG(180): #01 pc 00082957 /system/vendor/lib/egl/libGLESv2_adreno.so (rb_gpuprogram_loadsamplers+738)
03-26 16:03:51.327: I/DEBUG(180): #02 pc 000677bb /system/vendor/lib/egl/libGLESv2_adreno.so (load_samplers+430)
03-26 16:03:51.328: I/DEBUG(180): #03 pc 0005a51d /system/vendor/lib/egl/libGLESv2_adreno.so (core_glDrawElementsInstancedXXX+392)
03-26 16:03:51.328: I/DEBUG(180): #04 pc 0005a671 /system/vendor/lib/egl/libGLESv2_adreno.so (core_glDrawElements+10)
03-26 16:03:51.328: I/DEBUG(180): #05 pc 000499a3 /system/vendor/lib/egl/libGLESv2_adreno.so (glDrawElements+28)
03-26 16:03:51.328: I/DEBUG(180): #06 pc 00121519 /data/app/nonisoft.limball-1/lib/arm/libcocos2dcpp.so (cocos2d::Renderer::drawBatchedQuads()+292)
03-26 16:03:51.328: I/DEBUG(180): #07 pc 001215d1 /data/app/nonisoft.limball-1/lib/arm/libcocos2dcpp.so (cocos2d::Renderer::flushQuads()+16)
03-26 16:03:51.328: I/DEBUG(180): #08 pc 001215f7 /data/app/nonisoft.limball-1/lib/arm/libcocos2dcpp.so (cocos2d::Renderer::flush2D()+4)
03-26 16:03:51.328: I/DEBUG(180): #09 pc 00121609 /data/app/nonisoft.limball-1/lib/arm/libcocos2dcpp.so (cocos2d::Renderer::flush()+4)
03-26 16:03:51.328: I/DEBUG(180): #10 pc 001217f3 /data/app/nonisoft.limball-1/lib/arm/libcocos2dcpp.so (cocos2d::Renderer::processRenderCommand(cocos2d::RenderCommand*)+476)
03-26 16:03:51.328: I/DEBUG(180): #11 pc 0012195f /data/app/nonisoft.limball-1/lib/arm/libcocos2dcpp.so (cocos2d::Renderer::visitRenderQueue(cocos2d::RenderQueue&)+238)
03-26 16:03:51.328: I/DEBUG(180): #12 pc 0012195f /data/app/nonisoft.limball-1/lib/arm/libcocos2dcpp.so (cocos2d::Renderer::visitRenderQueue(cocos2d::RenderQueue&)+238)
03-26 16:03:51.329: I/DEBUG(180): #13 pc 0012239b /data/app/nonisoft.limball-1/lib/arm/libcocos2dcpp.so (cocos2d::Renderer::render()+42)
03-26 16:03:51.329: I/DEBUG(180): #14 pc 000f8e51 /data/app/nonisoft.limball-1/lib/arm/libcocos2dcpp.so (cocos2d::Scene::render(cocos2d::Renderer*)+204)
03-26 16:03:51.329: I/DEBUG(180): #15 pc 0010f045 /data/app/nonisoft.limball-1/lib/arm/libcocos2dcpp.so (cocos2d::Director::drawScene()+124)
03-26 16:03:51.329: I/DEBUG(180): #16 pc 0010f0ff /data/app/nonisoft.limball-1/lib/arm/libcocos2dcpp.so (cocos2d::DisplayLinkDirector::mainLoop()+38)
03-26 16:03:51.329: I/DEBUG(180): #17 pc 00132201 /data/dalvik-cache/arm/data@app@nonisoft.limball-1@base.apk@classes.dex
03-26 16:03:51.320: W/debuggerd(180): type=1400 audit(0.0:501): avc: denied { read } for name=“kgsl-3d0” dev=“tmpfs” ino=6028 scontext=u:r:debuggerd:s0 tcontext=u:object_r:gpu_device:s0 tclass=chr_file
03-26 16:03:51.320: W/debuggerd(180): type=1400 audit(0.0:502): avc: denied { read } for name=“kgsl-3d0” dev=“tmpfs” ino=6028 scontext=u:r:debuggerd:s0 tcontext=u:object_r:gpu_device:s0 tclass=chr_file
03-26 16:03:51.475: W/ScreenOrientationListener(30704): Removing an inexistent observer!
03-26 16:03:51.486: W/ScreenOrientationListener(30704): Removing an inexistent observer!
03-26 16:03:52.210: W/debuggerd(180): type=1400 audit(0.0:503): avc: denied { read } for name=“kgsl-3d0” dev=“tmpfs” ino=6028 scontext=u:r:debuggerd:s0 tcontext=u:object_r:gpu_device:s0 tclass=chr_file
03-26 16:03:52.210: W/debuggerd(180): type=1400 audit(0.0:504): avc: denied { read } for name=“kgsl-3d0” dev=“tmpfs” ino=6028 scontext=u:r:debuggerd:s0 tcontext=u:object_r:gpu_device:s0 tclass=chr_file
03-26 16:03:52.332: I/DEBUG(180): Tombstone written to: /data/tombstones/tombstone_07
03-26 16:03:52.335: E/SharedPreferencesImpl(2009): Couldn’t create directory for SharedPreferences file shared_prefs/log_files.xml

Any idea on what’s happening? It looks like a bug of the OpenGL implementation of this device…

I’m struggling with a similar situation on the HTC One M8 running 5.0.1

I wonder if there’s an issue with how label textures(atlases) are getting generated? My next step would be as I mentioned creating a new hello world project. Does that crash too - it has a label(s) ? I’d be surprised if the dev team doesn’t have a nexus 5. I gather you need the target-19 then? Are you trying to target 5.x only devices? You could at least try target-10, but probably won’t help. You may also want to post on the android developer forums. Sorry can’t be much more help, this one is an oddball so far based on what you’ve posted.

The only kinda similar issue for ours was a few devices (Samsung GS2 and 2-3 others we know of) didn’t support specific shader code, but I wouldn’t bother going down that rabit hole. Hopefully you can find a work around.

If you do try a new test project and it crashes, let us know. That’d be interesting in a not fun way.

I could test the game on another Nexus 5 running Android 4.4.4, and it worked perfectly. I’m still unsure if it’s a weird problem of the other concrete device, or if there is a general problem with Nexus 5 running Android 5.0.1. As I mentioned in my second post, I’ve tested on other devices (not Nexus) running Android 5.0.1 and it works well.

Currently I’m using android-14 in APP_PLATFORM, because this is the minSDK that I’m targeting.

I still couldn’t perform a simple test. Unfortunately, we’re just a two persons team with a highly constrained budget, and we can only test on Nexus 5 (or other devices) whenever we can borrow it from a friend.

If I get to conclude something else, I’ll let you know.

Good to know. Yeah I’ve kept my one Nexus 5 test device on 4.4.4 for testing. Maybe I should try updating it since we’ll probably run into the same issue with our next update release.

Just to keep you posted, I could test it on a different Nexus 5 with Android 5.0.1, and the same problem occurs.

Ok, so finally, I could fix the problem. It wasn’t the device fault after all… as it is usually the case :smile:

I had a problem with the Java Native Interface (JNI). Basically, in every frame, I was creating a local reference but I wasn’t deleting it.

Now the game works great on the device! :smile:

By the way, the game has just been released in case you want to try it and provide feedback.
iOS Link: https://itunes.apple.com/app/limball/id882244191
Android Link: https://play.google.com/store/apps/details?id=nonisoft.limball

I may have a same issue.
Please, what do you mean by not deleting a local reference in every frame?

Hi,

Sorry for the (long long) delay. It’s been quite a long time since I wrote that code, but I explained it in my blog. Take a look and ask me further details if you’re still stuck with it.