mirror of
https://github.com/mauiaaron/apple2.git
synced 2025-01-14 03:30:53 +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) {
|
public synchronized void setCustomExceptionHandler(Apple2Activity activity) {
|
||||||
|
synchronized (this) {
|
||||||
|
if (homeDir == null) {
|
||||||
|
homeDir = Apple2DisksMenu.getDataDir(activity);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (mDefaultExceptionHandler != null) {
|
if (mDefaultExceptionHandler != null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mDefaultExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
|
mDefaultExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
|
||||||
|
|
||||||
final String homeDir = "/data/data/" + activity.getPackageName();
|
|
||||||
final Thread.UncaughtExceptionHandler defaultExceptionHandler = mDefaultExceptionHandler;
|
final Thread.UncaughtExceptionHandler defaultExceptionHandler = mDefaultExceptionHandler;
|
||||||
|
|
||||||
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
|
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
|
||||||
@Override
|
@Override
|
||||||
public void uncaughtException(Thread thread, Throwable t) {
|
public void uncaughtException(Thread thread, Throwable t) {
|
||||||
try {
|
try {
|
||||||
StackTraceElement[] stackTraceElements = t.getStackTrace();
|
Apple2CrashHandler.onUncaughtException(thread, t);
|
||||||
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());
|
|
||||||
} catch (Throwable terminator2) {
|
} catch (Throwable terminator2) {
|
||||||
// Yo dawg, I hear you like exceptions in your exception handler! ...
|
// Yo dawg, I hear you like exceptions in your exception handler! ...
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultExceptionHandler.uncaughtException(thread, t);
|
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) {
|
private File _javaCrashFile(Apple2Activity activity) {
|
||||||
return new File(Apple2DisksMenu.getDataDir(activity), javaCrashFileName);
|
return new File(homeDir, javaCrashFileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private File[] _nativeCrashFiles(Apple2Activity activity) {
|
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) {
|
private String _dumpPath2ProcessedPath(String crashPath) {
|
||||||
@ -329,7 +357,7 @@ public class Apple2CrashHandler {
|
|||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
/* ... */
|
/* ... */
|
||||||
}
|
}
|
||||||
++ attempts;
|
++attempts;
|
||||||
} while (attempts < maxAttempts);
|
} while (attempts < maxAttempts);
|
||||||
|
|
||||||
return attempts < maxAttempts;
|
return attempts < maxAttempts;
|
||||||
@ -396,14 +424,13 @@ public class Apple2CrashHandler {
|
|||||||
private final static String TAG = "Apple2CrashHandler";
|
private final static String TAG = "Apple2CrashHandler";
|
||||||
private final static Apple2CrashHandler sCrashHandler = new Apple2CrashHandler();
|
private final static Apple2CrashHandler sCrashHandler = new Apple2CrashHandler();
|
||||||
|
|
||||||
|
private String homeDir;
|
||||||
private Thread.UncaughtExceptionHandler mDefaultExceptionHandler;
|
private Thread.UncaughtExceptionHandler mDefaultExceptionHandler;
|
||||||
private AtomicBoolean mAlreadyRanCrashCheck = new AtomicBoolean(false);
|
private AtomicBoolean mAlreadyRanCrashCheck = new AtomicBoolean(false);
|
||||||
private AtomicBoolean mAlreadySentReport = new AtomicBoolean(false);
|
private AtomicBoolean mAlreadySentReport = new AtomicBoolean(false);
|
||||||
|
|
||||||
private static native void nativePerformCrash(int crashType); // testing
|
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);
|
private static native void nativeProcessCrash(String crashFilePath, String crashProcessedPath);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
<string name="crasher_processing">Processing…</string>
|
<string name="crasher_processing">Processing…</string>
|
||||||
<string name="crasher_processing_message">Processing crash reports…</string>
|
<string name="crasher_processing_message">Processing crash reports…</string>
|
||||||
<string name="crasher_send">Send crash report?</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_summary">Test crash generation</string>
|
||||||
<string name="crasher_title">Crash emulator</string>
|
<string name="crasher_title">Crash emulator</string>
|
||||||
<string name="crash_null">NULL-deref</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) {
|
void Java_org_deadc0de_apple2ix_Apple2CrashHandler_nativeProcessCrash(JNIEnv *env, jclass cls, jstring jCrashPath, jstring jOutputPath) {
|
||||||
if (!(crashHandler && crashHandler->processCrash)) {
|
if (!(crashHandler && crashHandler->processCrash)) {
|
||||||
return;
|
return;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user