void handleCrash(int signalNumber, siginfo_t *sigInfo, void *context) { static volatile sig_atomic_t fatal_error_in_progress = 0; if (fatal_error_in_progress) //Stop a signal loop. _exit(1); fatal_error_in_progress = 1; char *j; char *signumber = strdup(sys_signame[signalNumber]); upcase(signumber); asprintf(&j, "Crash Signal: %s, crashed on: %li, UID: %ld\n", signumber, (long) sigInfo->si_addr, (long) sigInfo->si_uid); //%x prints out the faulty memory address in hex LOGE("%s", j); const size_t max = 30; void *buffer[max]; std::ostringstream oss; bool encodingCrash = dumpBacktrace(oss, buffer, captureBacktrace(buffer, max)); LOGE("%s", oss.str().c_str()); if (encodingCrash) { pthread_t *id = (pthread_t *) malloc(sizeof(pthread_t)); pthread_create(id, NULL, notifyThread, NULL); pthread_join(*id, NULL); } call_old_signal_handler(signalNumber, sigInfo, context); }
void printStackTrace(unsigned int max_frames) { void* buffer[max_frames]; std::ostringstream oss; dumpBacktrace(oss, buffer, captureBacktrace(buffer, max_frames)); __android_log_print(ANDROID_LOG_DEBUG, TAG, "%s", oss.str().c_str()); }
void Ref::release() { CCASSERT(_referenceCount > 0, "reference count should be greater than 0"); if(_referenceCount <= 0){ return; } --_referenceCount; auto poolManager = PoolManager::getInstance(); if (_isInAutoPool&&poolManager->isClearing()) { _isInAutoPool = false; } if (_referenceCount == 0) { //auto poolManager = PoolManager::getInstance(); if (_isInAutoPool&&!poolManager->isClearing() )//&& poolManager->isObjectInPools(this)) { poolManager->removeObject(this); } #if defined(COCOS2D_DEBUG) && (COCOS2D_DEBUG > 0) // auto poolManager = PoolManager::getInstance(); // if (!poolManager->getCurrentPool()->isClearing() && poolManager->isObjectInPools(this)) // { // } // Trigger an assert if the reference count is 0 but the Ref is still in autorelease pool. // This happens when 'autorelease/release' were not used in pairs with 'new/retain'. // // Wrong usage (1): // // auto obj = Node::create(); // Ref = 1, but it's an autorelease Ref which means it was in the autorelease pool. // obj->autorelease(); // Wrong: If you wish to invoke autorelease several times, you should retain `obj` first. // // Wrong usage (2): // // auto obj = Node::create(); // obj->release(); // Wrong: obj is an autorelease Ref, it will be released when clearing current pool. // // Correct usage (1): // // auto obj = Node::create(); // |- new Node(); // `new` is the pair of the `autorelease` of next line // |- autorelease(); // The pair of `new Node`. // // obj->retain(); // obj->autorelease(); // This `autorelease` is the pair of `retain` of previous line. // // Correct usage (2): // // auto obj = Node::create(); // obj->retain(); // obj->release(); // This `release` is the pair of `retain` of previous line. // CCASSERT(false, "The reference shouldn't be 0 because it is still in autorelease pool."); // } #endif #if CC_REF_LEAK_DETECTION untrackRef(this); #endif if ( g_performanceCrashSwitch && _isInAutoPool && !poolManager->isClearing() ) { #ifdef CC_ENABLE_BACKTRACE const size_t max = 30; void* buffer[max]; dumpBacktrace( buffer, captureBacktrace(buffer, max)); #endif int *pTest = NULL; *pTest = 123456; } delete this; } }
void getStackTrace(vector<InstructionPointer>& stackTrace, size_t skip) { stackTrace.clear(); captureBacktrace(skip + 1, stackTrace); }