Add some paranoid checks hoping to fix crashes reported in Google Play developer console.

This commit is contained in:
Henrik Rydgard 2016-04-09 18:21:31 +02:00
parent 774539dea8
commit 4197148dc4
8 changed files with 83 additions and 42 deletions

View File

@ -677,7 +677,3 @@ bool ElfReader::LoadSymbols()
} }
return hasSymbols; return hasSymbols;
} }

View File

@ -1703,29 +1703,29 @@ void __KernelReSchedule(const char *reason)
// Execute any pending events while we're doing scheduling. // Execute any pending events while we're doing scheduling.
CoreTiming::Advance(); CoreTiming::Advance();
if (__IsInInterrupt() || !__KernelIsDispatchEnabled()) if (__IsInInterrupt() || !__KernelIsDispatchEnabled()) {
{
// Threads don't get changed within interrupts or while dispatch is disabled. // Threads don't get changed within interrupts or while dispatch is disabled.
reason = "In Interrupt Or Callback"; reason = "In Interrupt Or Callback";
return; return;
} }
Thread *nextThread = __KernelNextThread(); Thread *nextThread = __KernelNextThread();
if (nextThread) if (nextThread) {
__KernelSwitchContext(nextThread, reason); __KernelSwitchContext(nextThread, reason);
}
// Otherwise, no need to switch. // Otherwise, no need to switch.
} }
void __KernelReSchedule(bool doCallbacks, const char *reason) void __KernelReSchedule(bool doCallbacks, const char *reason)
{ {
Thread *thread = __GetCurrentThread(); Thread *thread = __GetCurrentThread();
if (doCallbacks) if (doCallbacks && thread != nullptr) {
{ thread->isProcessingCallbacks = doCallbacks;
if (thread)
thread->isProcessingCallbacks = doCallbacks;
} }
// Note - this calls the function above, not this one. Overloading...
__KernelReSchedule(reason); __KernelReSchedule(reason);
if (doCallbacks && thread != NULL && thread->GetUID() == currentThread) { if (doCallbacks && thread != nullptr && thread->GetUID() == currentThread) {
if (thread->isRunning()) { if (thread->isRunning()) {
thread->isProcessingCallbacks = false; thread->isProcessingCallbacks = false;
} }

View File

@ -155,15 +155,18 @@ namespace Reporting
if (output == NULL) if (output == NULL)
output = &theVoid; output = &theVoid;
if (http.Resolve(ServerHostname(), ServerPort())) const char *serverHost = ServerHostname();
{ if (!serverHost)
return false;
if (http.Resolve(serverHost, ServerPort())) {
http.Connect(); http.Connect();
http.POST(uri, data, mimeType, output); http.POST(uri, data, mimeType, output);
http.Disconnect(); http.Disconnect();
result = true; return true;
} else {
return false;
} }
return result;
} }
std::string StripTrailingNull(const std::string &str) std::string StripTrailingNull(const std::string &str)

View File

@ -206,6 +206,9 @@ int PlayBackgroundAudio() {
// last changed... (to prevent crazy amount of reads when skipping through a list) // last changed... (to prevent crazy amount of reads when skipping through a list)
if (!at3Reader && bgGamePath.size() && (time_now_d() - gameLastChanged > 0.5)) { if (!at3Reader && bgGamePath.size() && (time_now_d() - gameLastChanged > 0.5)) {
// Grab some audio from the current game and play it. // Grab some audio from the current game and play it.
if (!g_gameInfoCache)
return 0; // race condition?
GameInfo *gameInfo = g_gameInfoCache->GetInfo(NULL, bgGamePath, GAMEINFO_WANTSND); GameInfo *gameInfo = g_gameInfoCache->GetInfo(NULL, bgGamePath, GAMEINFO_WANTSND);
if (!gameInfo) if (!gameInfo)
return 0; return 0;

View File

@ -611,7 +611,9 @@ void NativeShutdownGraphics() {
delete g_gameInfoCache; delete g_gameInfoCache;
g_gameInfoCache = nullptr; g_gameInfoCache = nullptr;
uiTexture->Release(); if (uiTexture->Release()) {
uiTexture = nullptr;
}
delete uiContext; delete uiContext;
uiContext = NULL; uiContext = NULL;
@ -619,7 +621,10 @@ void NativeShutdownGraphics() {
ui_draw2d.Shutdown(); ui_draw2d.Shutdown();
ui_draw2d_front.Shutdown(); ui_draw2d_front.Shutdown();
thin3d->Release(); // TODO: Reconsider this annoying ref counting stuff.
if (thin3d->Release()) {
thin3d = nullptr;
}
} }
void TakeScreenshot() { void TakeScreenshot() {

View File

@ -73,19 +73,22 @@ bool OpenSLWrap_Init(AndroidAudioCallback cb, int _FramesPerBuffer, int _SampleR
framesPerBuffer = 256; framesPerBuffer = 256;
if (framesPerBuffer < 32) if (framesPerBuffer < 32)
framesPerBuffer = 32; framesPerBuffer = 32;
if (framesPerBuffer > 4096)
framesPerBuffer = 4096;
sampleRate = _SampleRate; sampleRate = _SampleRate;
if (sampleRate != 44100 && sampleRate != 48000) { if (sampleRate != 44100 && sampleRate != 48000) {
ELOG("Invalid sample rate %i - choosing 44100", sampleRate); ELOG("Invalid sample rate %i - choosing 44100", sampleRate);
sampleRate = 44100; sampleRate = 44100;
} }
buffer[0] = new short[framesPerBuffer * 2];
buffer[1] = new short[framesPerBuffer * 2];
SLresult result; SLresult result;
// create engine // create engine
result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL); result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
assert(SL_RESULT_SUCCESS == result); if (result != SL_RESULT_SUCCESS) {
ELOG("OpenSL ES: Failed to create the engine: %d", (int)result);
return false;
}
result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE); result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
assert(SL_RESULT_SUCCESS == result); assert(SL_RESULT_SUCCESS == result);
result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine); result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
@ -98,7 +101,7 @@ bool OpenSLWrap_Init(AndroidAudioCallback cb, int _FramesPerBuffer, int _SampleR
SLuint32 sr = SL_SAMPLINGRATE_44_1; SLuint32 sr = SL_SAMPLINGRATE_44_1;
if (sampleRate == 48000) { if (sampleRate == 48000) {
sr = SL_SAMPLINGRATE_48; sr = SL_SAMPLINGRATE_48;
} } // Don't allow any other sample rates.
SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2}; SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2};
SLDataFormat_PCM format_pcm = { SLDataFormat_PCM format_pcm = {
@ -121,7 +124,11 @@ bool OpenSLWrap_Init(AndroidAudioCallback cb, int _FramesPerBuffer, int _SampleR
const SLInterfaceID ids[2] = {SL_IID_BUFFERQUEUE, SL_IID_VOLUME}; const SLInterfaceID ids[2] = {SL_IID_BUFFERQUEUE, SL_IID_VOLUME};
const SLboolean req[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE}; const SLboolean req[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
result = (*engineEngine)->CreateAudioPlayer(engineEngine, &bqPlayerObject, &audioSrc, &audioSnk, 2, ids, req); result = (*engineEngine)->CreateAudioPlayer(engineEngine, &bqPlayerObject, &audioSrc, &audioSnk, 2, ids, req);
assert(SL_RESULT_SUCCESS == result); if (result != SL_RESULT_SUCCESS) {
ELOG("OpenSL ES: CreateAudioPlayer failed: %d", (int)result);
// Should really tear everything down here. Sigh.
return false;
}
result = (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE); result = (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE);
assert(SL_RESULT_SUCCESS == result); assert(SL_RESULT_SUCCESS == result);
@ -138,6 +145,9 @@ bool OpenSLWrap_Init(AndroidAudioCallback cb, int _FramesPerBuffer, int _SampleR
assert(SL_RESULT_SUCCESS == result); assert(SL_RESULT_SUCCESS == result);
// Render and enqueue a first buffer. (or should we just play the buffer empty?) // Render and enqueue a first buffer. (or should we just play the buffer empty?)
buffer[0] = new short[framesPerBuffer * 2];
buffer[1] = new short[framesPerBuffer * 2];
curBuffer = 0; curBuffer = 0;
audioCallback(buffer[curBuffer], framesPerBuffer); audioCallback(buffer[curBuffer], framesPerBuffer);
@ -151,40 +161,44 @@ bool OpenSLWrap_Init(AndroidAudioCallback cb, int _FramesPerBuffer, int _SampleR
// shut down the native audio system // shut down the native audio system
void OpenSLWrap_Shutdown() { void OpenSLWrap_Shutdown() {
SLresult result; if (bqPlayerPlay) {
ILOG("OpenSLWrap_Shutdown - stopping playback"); ILOG("OpenSLWrap_Shutdown - stopping playback");
result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_STOPPED); SLresult result;
if (SL_RESULT_SUCCESS != result) { result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_STOPPED);
ELOG("SetPlayState failed"); if (SL_RESULT_SUCCESS != result) {
ELOG("SetPlayState failed");
}
} }
ILOG("OpenSLWrap_Shutdown - deleting player object"); ILOG("OpenSLWrap_Shutdown - deleting player object");
if (bqPlayerObject != NULL) { if (bqPlayerObject) {
(*bqPlayerObject)->Destroy(bqPlayerObject); (*bqPlayerObject)->Destroy(bqPlayerObject);
bqPlayerObject = NULL; bqPlayerObject = nullptr;
bqPlayerPlay = NULL; bqPlayerPlay = nullptr;
bqPlayerBufferQueue = NULL; bqPlayerBufferQueue = nullptr;
bqPlayerMuteSolo = NULL; bqPlayerMuteSolo = nullptr;
bqPlayerVolume = NULL; bqPlayerVolume = nullptr;
} }
ILOG("OpenSLWrap_Shutdown - deleting mix object"); ILOG("OpenSLWrap_Shutdown - deleting mix object");
if (outputMixObject != NULL) { if (outputMixObject) {
(*outputMixObject)->Destroy(outputMixObject); (*outputMixObject)->Destroy(outputMixObject);
outputMixObject = NULL; outputMixObject = nullptr;
} }
ILOG("OpenSLWrap_Shutdown - deleting engine object"); ILOG("OpenSLWrap_Shutdown - deleting engine object");
if (engineObject != NULL) { if (engineObject) {
(*engineObject)->Destroy(engineObject); (*engineObject)->Destroy(engineObject);
engineObject = NULL; engineObject = nullptr;
engineEngine = NULL; engineEngine = nullptr;
} }
delete [] buffer[0]; delete [] buffer[0];
delete [] buffer[1]; delete [] buffer[1];
buffer[0] = nullptr;
buffer[1] = nullptr;
ILOG("OpenSLWrap_Shutdown - finished"); ILOG("OpenSLWrap_Shutdown - finished");
} }

View File

@ -11,6 +11,8 @@
#include <vector> #include <vector>
#include <string> #include <string>
#include "base/logging.h"
class Matrix4x4; class Matrix4x4;
enum T3DBlendEquation : int { enum T3DBlendEquation : int {
@ -212,8 +214,20 @@ public:
Thin3DObject() : refcount_(1) {} Thin3DObject() : refcount_(1) {}
virtual ~Thin3DObject() {} virtual ~Thin3DObject() {}
// TODO: Reconsider this annoying ref counting stuff.
virtual void AddRef() { refcount_++; } virtual void AddRef() { refcount_++; }
virtual void Release() { refcount_--; if (!refcount_) delete this; } virtual bool Release() {
if (refcount_ > 0 && refcount_ < 10000) {
refcount_--;
if (refcount_ == 0) {
delete this;
return true;
}
} else {
ELOG("Refcount (%d) invalid for object %p - corrupt?", refcount_, this);
}
return false;
}
private: private:
int refcount_; int refcount_;

View File

@ -58,6 +58,9 @@ void UIScreen::update(InputState &input) {
void UIScreen::preRender() { void UIScreen::preRender() {
Thin3DContext *thin3d = screenManager()->getThin3DContext(); Thin3DContext *thin3d = screenManager()->getThin3DContext();
if (!thin3d) {
return;
}
thin3d->Begin(true, 0xFF000000, 0.0f, 0); thin3d->Begin(true, 0xFF000000, 0.0f, 0);
T3DViewport viewport; T3DViewport viewport;
@ -73,6 +76,9 @@ void UIScreen::preRender() {
void UIScreen::postRender() { void UIScreen::postRender() {
Thin3DContext *thin3d = screenManager()->getThin3DContext(); Thin3DContext *thin3d = screenManager()->getThin3DContext();
if (!thin3d) {
return;
}
thin3d->End(); thin3d->End();
} }