mirror of
https://github.com/mauiaaron/apple2.git
synced 2024-12-26 15:29:19 +00:00
Handle Java exceptions within Java to the best of our ability
This commit is contained in:
parent
e51aaa1695
commit
b5de4222c3
@ -83,39 +83,26 @@ public class Apple2CrashHandler {
|
||||
}
|
||||
|
||||
public synchronized void setCustomExceptionHandler(Apple2Activity activity) {
|
||||
synchronized (this) {
|
||||
if (homeDir == null) {
|
||||
homeDir = Apple2DisksMenu.getDataDir(activity);
|
||||
}
|
||||
}
|
||||
if (mDefaultExceptionHandler != null) {
|
||||
return;
|
||||
}
|
||||
mDefaultExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
|
||||
|
||||
final String homeDir = "/data/data/" + activity.getPackageName();
|
||||
final Thread.UncaughtExceptionHandler defaultExceptionHandler = mDefaultExceptionHandler;
|
||||
|
||||
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
|
||||
@Override
|
||||
public void uncaughtException(Thread thread, Throwable t) {
|
||||
try {
|
||||
StackTraceElement[] stackTraceElements = t.getStackTrace();
|
||||
StringBuffer traceBuffer = new StringBuffer();
|
||||
|
||||
// append the Java stack trace
|
||||
traceBuffer.append(t.getClass().getName());
|
||||
traceBuffer.append("\n");
|
||||
final int maxTraceSize = 2048 + 1024 + 512; // probably should keep this less than a standard Linux PAGE_SIZE
|
||||
for (StackTraceElement elt : stackTraceElements) {
|
||||
traceBuffer.append(elt.toString());
|
||||
traceBuffer.append("\n");
|
||||
if (traceBuffer.length() >= maxTraceSize) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
traceBuffer.append("\n");
|
||||
|
||||
nativeOnUncaughtException(homeDir, traceBuffer.toString());
|
||||
Apple2CrashHandler.onUncaughtException(thread, t);
|
||||
} catch (Throwable terminator2) {
|
||||
// Yo dawg, I hear you like exceptions in your exception handler! ...
|
||||
}
|
||||
|
||||
defaultExceptionHandler.uncaughtException(thread, t);
|
||||
}
|
||||
});
|
||||
@ -271,8 +258,49 @@ public class Apple2CrashHandler {
|
||||
/* ... */
|
||||
}
|
||||
|
||||
private static void onUncaughtException(Thread thread, Throwable t) {
|
||||
StackTraceElement[] stackTraceElements = t.getStackTrace();
|
||||
StringBuffer traceBuffer = new StringBuffer();
|
||||
|
||||
// append the Java stack trace
|
||||
traceBuffer.append("NAME: ").append(t.getClass().getName()).append("\n");
|
||||
traceBuffer.append("MESSAGE: ").append(t.getMessage()).append("\n");
|
||||
final int maxTraceSize = 2048 + 1024 + 512; // probably should keep this less than a standard Linux PAGE_SIZE
|
||||
for (StackTraceElement elt : stackTraceElements) {
|
||||
traceBuffer.append(elt.toString());
|
||||
traceBuffer.append("\n");
|
||||
if (traceBuffer.length() >= maxTraceSize) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
traceBuffer.append("\n");
|
||||
|
||||
final int maxAttempts = 5;
|
||||
int attempts = 0;
|
||||
do {
|
||||
try {
|
||||
BufferedWriter writer = new BufferedWriter(new FileWriter(new File(sCrashHandler.homeDir, javaCrashFileName), /*append:*/true));
|
||||
writer.append(traceBuffer);
|
||||
writer.flush();
|
||||
writer.close();
|
||||
break;
|
||||
} catch (InterruptedIOException ie) {
|
||||
/* EINTR, EAGAIN ... */
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Exception attempting to write data : " + e);
|
||||
}
|
||||
|
||||
try {
|
||||
Thread.sleep(100, 0);
|
||||
} catch (InterruptedException e) {
|
||||
/* ... */
|
||||
}
|
||||
++attempts;
|
||||
} while (attempts < maxAttempts);
|
||||
}
|
||||
|
||||
private File _javaCrashFile(Apple2Activity activity) {
|
||||
return new File(Apple2DisksMenu.getDataDir(activity), javaCrashFileName);
|
||||
return new File(homeDir, javaCrashFileName);
|
||||
}
|
||||
|
||||
private File[] _nativeCrashFiles(Apple2Activity activity) {
|
||||
@ -297,7 +325,7 @@ public class Apple2CrashHandler {
|
||||
}
|
||||
};
|
||||
|
||||
return new File(Apple2DisksMenu.getDataDir(activity)).listFiles(dmpFilter);
|
||||
return new File(homeDir).listFiles(dmpFilter);
|
||||
}
|
||||
|
||||
private String _dumpPath2ProcessedPath(String crashPath) {
|
||||
@ -329,7 +357,7 @@ public class Apple2CrashHandler {
|
||||
} catch (InterruptedException e) {
|
||||
/* ... */
|
||||
}
|
||||
++ attempts;
|
||||
++attempts;
|
||||
} while (attempts < maxAttempts);
|
||||
|
||||
return attempts < maxAttempts;
|
||||
@ -396,14 +424,13 @@ public class Apple2CrashHandler {
|
||||
private final static String TAG = "Apple2CrashHandler";
|
||||
private final static Apple2CrashHandler sCrashHandler = new Apple2CrashHandler();
|
||||
|
||||
private String homeDir;
|
||||
private Thread.UncaughtExceptionHandler mDefaultExceptionHandler;
|
||||
private AtomicBoolean mAlreadyRanCrashCheck = new AtomicBoolean(false);
|
||||
private AtomicBoolean mAlreadySentReport = new AtomicBoolean(false);
|
||||
|
||||
private static native void nativePerformCrash(int crashType); // testing
|
||||
|
||||
private static native void nativeOnUncaughtException(String home, String trace);
|
||||
|
||||
private static native void nativeProcessCrash(String crashFilePath, String crashProcessedPath);
|
||||
|
||||
}
|
||||
|
@ -24,7 +24,7 @@
|
||||
<string name="crasher_processing">Processing…</string>
|
||||
<string name="crasher_processing_message">Processing crash reports…</string>
|
||||
<string name="crasher_send">Send crash report?</string>
|
||||
<string name="crasher_send_message">Do you want to send a crash report to the developer?</string>
|
||||
<string name="crasher_send_message">Sorry there has been a problem. Do you want to send a crash report to the developer?</string>
|
||||
<string name="crasher_summary">Test crash generation</string>
|
||||
<string name="crasher_title">Crash emulator</string>
|
||||
<string name="crash_null">NULL-deref</string>
|
||||
|
@ -105,42 +105,6 @@ void Java_org_deadc0de_apple2ix_Apple2CrashHandler_nativePerformCrash(JNIEnv *en
|
||||
}
|
||||
}
|
||||
|
||||
#define _JAVA_CRASH_NAME "/jcrash.txt" // this should match the Java side
|
||||
#define _HALF_PAGE_SIZE (PAGE_SIZE>>1)
|
||||
|
||||
void Java_org_deadc0de_apple2ix_Apple2CrashHandler_nativeOnUncaughtException(JNIEnv *env, jclass cls, jstring jhome, jstring jstr) {
|
||||
RELEASE_ERRLOG("Uncaught Java Exception ...");
|
||||
|
||||
// Write to /data/data/org.deadc0de.apple2ix.basic/jcrash.txt
|
||||
const char *home = (*env)->GetStringUTFChars(env, jhome, NULL);
|
||||
char *q = (char *)home;
|
||||
char buf[_HALF_PAGE_SIZE] = { 0 };
|
||||
const char *p0 = &buf[0];
|
||||
char *p = (char *)p0;
|
||||
while (*q && (p-p0 < _HALF_PAGE_SIZE-1)) {
|
||||
*p++ = *q++;
|
||||
}
|
||||
(*env)->ReleaseStringUTFChars(env, jhome, home);
|
||||
q = &_JAVA_CRASH_NAME[0];
|
||||
while (*q && (p-p0 < _HALF_PAGE_SIZE-1)) {
|
||||
*p++ = *q++;
|
||||
}
|
||||
|
||||
int fd = TEMP_FAILURE_RETRY(open(buf, (O_CREAT|O_APPEND|O_WRONLY), (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)));
|
||||
if (fd == -1) {
|
||||
RELEASE_ERRLOG("OOPS, could not create/write to java crash file");
|
||||
return;
|
||||
}
|
||||
|
||||
const char *str = (*env)->GetStringUTFChars(env, jstr, NULL);
|
||||
jsize len = (*env)->GetStringUTFLength(env, jstr);
|
||||
TEMP_FAILURE_RETRY(write(fd, str, len));
|
||||
(*env)->ReleaseStringUTFChars(env, jstr, str);
|
||||
|
||||
TEMP_FAILURE_RETRY(fsync(fd));
|
||||
TEMP_FAILURE_RETRY(close(fd));
|
||||
}
|
||||
|
||||
void Java_org_deadc0de_apple2ix_Apple2CrashHandler_nativeProcessCrash(JNIEnv *env, jclass cls, jstring jCrashPath, jstring jOutputPath) {
|
||||
if (!(crashHandler && crashHandler->processCrash)) {
|
||||
return;
|
||||
|
Loading…
Reference in New Issue
Block a user