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;
}

View File

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

View File

@ -155,15 +155,18 @@ namespace Reporting
if (output == NULL)
output = &theVoid;
if (http.Resolve(ServerHostname(), ServerPort()))
{
const char *serverHost = ServerHostname();
if (!serverHost)
return false;
if (http.Resolve(serverHost, ServerPort())) {
http.Connect();
http.POST(uri, data, mimeType, output);
http.Disconnect();
result = true;
return true;
} else {
return false;
}
return result;
}
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)
if (!at3Reader && bgGamePath.size() && (time_now_d() - gameLastChanged > 0.5)) {
// 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);
if (!gameInfo)
return 0;

View File

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

View File

@ -73,19 +73,22 @@ bool OpenSLWrap_Init(AndroidAudioCallback cb, int _FramesPerBuffer, int _SampleR
framesPerBuffer = 256;
if (framesPerBuffer < 32)
framesPerBuffer = 32;
if (framesPerBuffer > 4096)
framesPerBuffer = 4096;
sampleRate = _SampleRate;
if (sampleRate != 44100 && sampleRate != 48000) {
ELOG("Invalid sample rate %i - choosing 44100", sampleRate);
sampleRate = 44100;
}
buffer[0] = new short[framesPerBuffer * 2];
buffer[1] = new short[framesPerBuffer * 2];
SLresult result;
// create engine
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);
assert(SL_RESULT_SUCCESS == result);
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;
if (sampleRate == 48000) {
sr = SL_SAMPLINGRATE_48;
}
} // Don't allow any other sample rates.
SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2};
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 SLboolean req[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
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);
assert(SL_RESULT_SUCCESS == result);
@ -138,6 +145,9 @@ bool OpenSLWrap_Init(AndroidAudioCallback cb, int _FramesPerBuffer, int _SampleR
assert(SL_RESULT_SUCCESS == result);
// 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;
audioCallback(buffer[curBuffer], framesPerBuffer);
@ -151,40 +161,44 @@ bool OpenSLWrap_Init(AndroidAudioCallback cb, int _FramesPerBuffer, int _SampleR
// shut down the native audio system
void OpenSLWrap_Shutdown() {
SLresult result;
ILOG("OpenSLWrap_Shutdown - stopping playback");
result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_STOPPED);
if (SL_RESULT_SUCCESS != result) {
ELOG("SetPlayState failed");
if (bqPlayerPlay) {
ILOG("OpenSLWrap_Shutdown - stopping playback");
SLresult result;
result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_STOPPED);
if (SL_RESULT_SUCCESS != result) {
ELOG("SetPlayState failed");
}
}
ILOG("OpenSLWrap_Shutdown - deleting player object");
if (bqPlayerObject != NULL) {
if (bqPlayerObject) {
(*bqPlayerObject)->Destroy(bqPlayerObject);
bqPlayerObject = NULL;
bqPlayerPlay = NULL;
bqPlayerBufferQueue = NULL;
bqPlayerMuteSolo = NULL;
bqPlayerVolume = NULL;
bqPlayerObject = nullptr;
bqPlayerPlay = nullptr;
bqPlayerBufferQueue = nullptr;
bqPlayerMuteSolo = nullptr;
bqPlayerVolume = nullptr;
}
ILOG("OpenSLWrap_Shutdown - deleting mix object");
if (outputMixObject != NULL) {
if (outputMixObject) {
(*outputMixObject)->Destroy(outputMixObject);
outputMixObject = NULL;
outputMixObject = nullptr;
}
ILOG("OpenSLWrap_Shutdown - deleting engine object");
if (engineObject != NULL) {
if (engineObject) {
(*engineObject)->Destroy(engineObject);
engineObject = NULL;
engineEngine = NULL;
engineObject = nullptr;
engineEngine = nullptr;
}
delete [] buffer[0];
delete [] buffer[1];
buffer[0] = nullptr;
buffer[1] = nullptr;
ILOG("OpenSLWrap_Shutdown - finished");
}

View File

@ -11,6 +11,8 @@
#include <vector>
#include <string>
#include "base/logging.h"
class Matrix4x4;
enum T3DBlendEquation : int {
@ -212,8 +214,20 @@ public:
Thin3DObject() : refcount_(1) {}
virtual ~Thin3DObject() {}
// TODO: Reconsider this annoying ref counting stuff.
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:
int refcount_;

View File

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