mirror of
https://github.com/corda/corda.git
synced 2024-12-29 09:18:58 +00:00
Squashed commit of the following: (#32)
commit a25c09bb738e7e82d2dfd909381ba052f7b69687 Merge: aa6664214 92af5d169 Author: Joel Dice <joel.dice@gmail.com> Date: Tue Sep 5 11:38:08 2017 -0600 Merge pull request #545 from corda/chrisr3-uncaught-exceptions Support Thread.uncaughtExceptionHandler with OpenJDK commit aa666421499d0e9ed46b6c745a93abd9998a58b0 Merge: dc8c99bd2 1cb11e964 Author: Joel Dice <joel.dice@gmail.com> Date: Tue Sep 5 11:23:41 2017 -0600 Merge pull request #546 from corda/chrisr3-werror Fix "fallthrough" warnings with recent GCC. commit dc8c99bd2f045c787f2c322cd65f866626fa9461 Author: Joel Dice <joel.dice@gmail.com> Date: Tue Sep 5 11:17:54 2017 -0600 fix bootimage-test build regression commit 1cb11e964fab925e9d98373ba58e181b1a1f11fd Author: Chris Rankin <chris.rankin@r3.com> Date: Tue Sep 5 10:25:48 2017 +0100 Fix "fallthrough" warnings with recent GCC. commit 92af5d169dbfb7b9b9f5b667b0dc71ca7b98b416 Author: Chris Rankin <chris.rankin@r3.com> Date: Mon Sep 4 17:26:31 2017 +0100 Ensure that the thread resources are only cleaned up once. commit 05d260f8bed68e3f999619aee338a781ba0f4c63 Author: Chris Rankin <chris.rankin@r3.com> Date: Mon Sep 4 17:10:04 2017 +0100 Test exception thrown from uncaught-exception handler. commit b1c5dca36163a876fba86221493883ddbd5fe805 Author: Chris Rankin <chris.rankin@r3.com> Date: Tue Aug 29 17:17:24 2017 +0100 Support Thread.uncaughtExceptionHandler.
This commit is contained in:
parent
e075e52377
commit
c0c75c3e19
@ -296,6 +296,10 @@ object makeJconstructor(Thread* t, GcMethod* vmMethod, int index = -1);
|
|||||||
|
|
||||||
object makeJfield(Thread* t, GcField* vmField, int index = -1);
|
object makeJfield(Thread* t, GcField* vmField, int index = -1);
|
||||||
|
|
||||||
|
void uncaughtException(Thread *t, GcThrowable *e);
|
||||||
|
|
||||||
|
void disposeThread(Thread *t);
|
||||||
|
|
||||||
#ifdef AVIAN_OPENJDK_SRC
|
#ifdef AVIAN_OPENJDK_SRC
|
||||||
void interceptFileOperations(Thread*, bool);
|
void interceptFileOperations(Thread*, bool);
|
||||||
#endif
|
#endif
|
||||||
@ -588,22 +592,15 @@ class MyClasspath : public Classpath {
|
|||||||
objectMonitor(t, t->javaThread, true);
|
objectMonitor(t, t->javaThread, true);
|
||||||
|
|
||||||
THREAD_RESOURCE0(t, {
|
THREAD_RESOURCE0(t, {
|
||||||
vm::acquire(t, t->javaThread);
|
|
||||||
t->clearFlag(Thread::ActiveFlag);
|
|
||||||
vm::notifyAll(t, t->javaThread);
|
|
||||||
vm::release(t, t->javaThread);
|
|
||||||
|
|
||||||
GcThrowable* e = t->exception;
|
GcThrowable* e = t->exception;
|
||||||
|
if (e != NULL) {
|
||||||
PROTECT(t, e);
|
PROTECT(t, e);
|
||||||
|
|
||||||
t->exception = 0;
|
t->exception = NULL;
|
||||||
|
uncaughtException(t, e);
|
||||||
|
}
|
||||||
|
|
||||||
t->m->processor->invoke(t,
|
disposeThread(t);
|
||||||
cast<GcMethod>(t, roots(t)->threadTerminated()),
|
|
||||||
t->javaThread->group(),
|
|
||||||
t->javaThread);
|
|
||||||
|
|
||||||
t->exception = e;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
GcMethod* method = resolveMethod(
|
GcMethod* method = resolveMethod(
|
||||||
@ -972,6 +969,43 @@ class EmbeddedFile {
|
|||||||
unsigned pathLength;
|
unsigned pathLength;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void uncaughtException(Thread *t, GcThrowable *e)
|
||||||
|
{
|
||||||
|
GcMethod* dispatch = resolveMethod(t,
|
||||||
|
roots(t)->bootLoader(),
|
||||||
|
"java/lang/Thread",
|
||||||
|
"dispatchUncaughtException",
|
||||||
|
"(Ljava/lang/Throwable;)V");
|
||||||
|
if (dispatch != NULL) {
|
||||||
|
THREAD_RESOURCE0(t, {
|
||||||
|
if (t->exception != NULL) {
|
||||||
|
// We ignore any exceptions from the uncaught
|
||||||
|
// exception handler itself.
|
||||||
|
t->exception = NULL;
|
||||||
|
|
||||||
|
// The stack will be unwound when this resource is
|
||||||
|
// released, which means that uncaughtException()
|
||||||
|
// will not return. So repeat the thread clean-up here.
|
||||||
|
disposeThread(t);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
t->m->processor->invoke(t, dispatch, t->javaThread, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void disposeThread(Thread *t) {
|
||||||
|
vm::acquire(t, t->javaThread);
|
||||||
|
t->clearFlag(Thread::ActiveFlag);
|
||||||
|
vm::notifyAll(t, t->javaThread);
|
||||||
|
vm::release(t, t->javaThread);
|
||||||
|
|
||||||
|
t->m->processor->invoke(t,
|
||||||
|
cast<GcMethod>(t, roots(t)->threadTerminated()),
|
||||||
|
t->javaThread->group(),
|
||||||
|
t->javaThread);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef AVIAN_OPENJDK_SRC
|
#ifdef AVIAN_OPENJDK_SRC
|
||||||
int64_t JNICALL
|
int64_t JNICALL
|
||||||
getFileAttributes(Thread* t, GcMethod* method, uintptr_t* arguments)
|
getFileAttributes(Thread* t, GcMethod* method, uintptr_t* arguments)
|
||||||
|
@ -4029,13 +4029,13 @@ bool isLambda(Thread* t,
|
|||||||
GcCharArray* bootstrapArray,
|
GcCharArray* bootstrapArray,
|
||||||
GcInvocation* invocation)
|
GcInvocation* invocation)
|
||||||
{
|
{
|
||||||
GcMethod* bootstrap = cast<GcMethod>(t,
|
GcMethod* bootstrap = cast<GcMethodHandle>(t,
|
||||||
resolve(t,
|
resolve(t,
|
||||||
loader,
|
loader,
|
||||||
invocation->pool(),
|
invocation->pool(),
|
||||||
bootstrapArray->body()[0],
|
bootstrapArray->body()[0],
|
||||||
findMethodInClass,
|
findMethodInClass,
|
||||||
GcNoSuchMethodError::Type));
|
GcNoSuchMethodError::Type))->method();
|
||||||
PROTECT(t, bootstrap);
|
PROTECT(t, bootstrap);
|
||||||
|
|
||||||
return vm::strcmp(reinterpret_cast<const int8_t*>(
|
return vm::strcmp(reinterpret_cast<const int8_t*>(
|
||||||
@ -5191,14 +5191,8 @@ loop:
|
|||||||
"I"
|
"I"
|
||||||
")[B");
|
")[B");
|
||||||
|
|
||||||
GcReference* reference = cast<GcReference>(
|
GcMethodHandle* handle
|
||||||
t,
|
= cast<GcMethodHandle>(t,
|
||||||
singletonObject(
|
|
||||||
t, invocation->pool(), bootstrapArray->body()[2]));
|
|
||||||
int kind = reference->kind();
|
|
||||||
|
|
||||||
GcMethod* method
|
|
||||||
= cast<GcMethod>(t,
|
|
||||||
resolve(t,
|
resolve(t,
|
||||||
c->loader(),
|
c->loader(),
|
||||||
invocation->pool(),
|
invocation->pool(),
|
||||||
@ -5206,6 +5200,10 @@ loop:
|
|||||||
findMethodInClass,
|
findMethodInClass,
|
||||||
GcNoSuchMethodError::Type));
|
GcNoSuchMethodError::Type));
|
||||||
|
|
||||||
|
int kind = handle->kind();
|
||||||
|
|
||||||
|
GcMethod* method = handle->method();
|
||||||
|
|
||||||
jarray lambda = e->vtable->CallStaticObjectMethod(
|
jarray lambda = e->vtable->CallStaticObjectMethod(
|
||||||
e,
|
e,
|
||||||
lmfClass,
|
lmfClass,
|
||||||
|
@ -571,6 +571,7 @@ int printInstruction(uint8_t* code, unsigned& ip, const char* prefix)
|
|||||||
return fprintf(stderr, "wide astore %4d", read16(code, ip));
|
return fprintf(stderr, "wide astore %4d", read16(code, ip));
|
||||||
case iinc:
|
case iinc:
|
||||||
fprintf(stderr, "wide iinc %4d %4d", read16(code, ip), read16(code, ip));
|
fprintf(stderr, "wide iinc %4d %4d", read16(code, ip), read16(code, ip));
|
||||||
|
/* fallthrough */
|
||||||
case iload:
|
case iload:
|
||||||
return fprintf(stderr, "wide iload %4d", read16(code, ip));
|
return fprintf(stderr, "wide iload %4d", read16(code, ip));
|
||||||
case istore:
|
case istore:
|
||||||
@ -582,10 +583,10 @@ int printInstruction(uint8_t* code, unsigned& ip, const char* prefix)
|
|||||||
case ret:
|
case ret:
|
||||||
return fprintf(stderr, "wide ret %4d", read16(code, ip));
|
return fprintf(stderr, "wide ret %4d", read16(code, ip));
|
||||||
|
|
||||||
default: {
|
default:
|
||||||
fprintf(
|
fprintf(
|
||||||
stderr, "unknown wide instruction %2d %4d", instr, read16(code, ip));
|
stderr, "unknown wide instruction %2d %4d", instr, read16(code, ip));
|
||||||
}
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4105,6 +4105,7 @@ void enter(Thread* t, Thread::State s)
|
|||||||
} else {
|
} else {
|
||||||
// fall through to slow path
|
// fall through to slow path
|
||||||
}
|
}
|
||||||
|
/* fallthrough */
|
||||||
|
|
||||||
case Thread::ZombieState: {
|
case Thread::ZombieState: {
|
||||||
ACQUIRE_LOCK;
|
ACQUIRE_LOCK;
|
||||||
@ -6189,7 +6190,7 @@ GcCallSite* resolveDynamic(Thread* t, GcInvocation* invocation)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// `i` iterates through the bootstrap arguments (the +1 is because we skip
|
// `i` iterates through the bootstrap arguments (the +1 is because we skip
|
||||||
// the boostrap method's name), `it` iterates through the corresponding types
|
// the bootstrap method's name), `it` iterates through the corresponding types
|
||||||
// in the method signature
|
// in the method signature
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
while (i + 1 < bootstrapArray->length() && it.hasNext()) {
|
while (i + 1 < bootstrapArray->length() && it.hasNext()) {
|
||||||
|
71
sgx-jvm/avian/test/ThreadExceptions.java
Normal file
71
sgx-jvm/avian/test/ThreadExceptions.java
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
public class ThreadExceptions {
|
||||||
|
|
||||||
|
private static void expect(boolean v) {
|
||||||
|
if (! v) throw new RuntimeException("Expectation failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Handler implements Thread.UncaughtExceptionHandler {
|
||||||
|
public String message;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void uncaughtException(Thread t, Throwable e) {
|
||||||
|
message = e.getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
{ Thread thread = new Thread() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
throw new RuntimeException("TEST-DEFAULT-HANDLER");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Handler handler = new Handler();
|
||||||
|
Thread.setDefaultUncaughtExceptionHandler(handler);
|
||||||
|
thread.start();
|
||||||
|
thread.join();
|
||||||
|
|
||||||
|
expect("TEST-DEFAULT-HANDLER".equals(handler.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread.setDefaultUncaughtExceptionHandler(null);
|
||||||
|
|
||||||
|
{ Thread thread = new Thread() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
throw new RuntimeException("TEST-HANDLER");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Handler handler = new Handler();
|
||||||
|
thread.setUncaughtExceptionHandler(handler);
|
||||||
|
thread.start();
|
||||||
|
thread.join();
|
||||||
|
|
||||||
|
expect("TEST-HANDLER".equals(handler.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
{ Thread thread = new Thread() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
throw new RuntimeException("TEST-BAD-HANDLER");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Handler handler = new Handler() {
|
||||||
|
@Override
|
||||||
|
public void uncaughtException(Thread t, Throwable e) {
|
||||||
|
super.uncaughtException(t, e);
|
||||||
|
throw new IllegalStateException("BAD THING");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
thread.setUncaughtExceptionHandler(handler);
|
||||||
|
thread.start();
|
||||||
|
thread.join();
|
||||||
|
|
||||||
|
expect("TEST-BAD-HANDLER".equals(handler.message));
|
||||||
|
System.out.println("Exception from UncaughtExceptionHandler was ignored");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -6,7 +6,7 @@ public class Threads implements Runnable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
((Thread.UncaughtExceptionHandler) Thread.currentThread().getThreadGroup())
|
Thread.currentThread().getThreadGroup()
|
||||||
.uncaughtException(Thread.currentThread(), new Exception());
|
.uncaughtException(Thread.currentThread(), new Exception());
|
||||||
|
|
||||||
{ Threads test = new Threads();
|
{ Threads test = new Threads();
|
||||||
|
Loading…
Reference in New Issue
Block a user