aboutsummaryrefslogtreecommitdiff
path: root/nailgun_launcher
diff options
context:
space:
mode:
authorChristopher Vogt <oss.nsp@cvogt.org>2016-10-07 00:24:14 -0400
committerChristopher Vogt <oss.nsp@cvogt.org>2016-10-07 20:05:57 -0400
commit8529a70358921af282920c216a81609292c8ba6a (patch)
tree04a23a27b41c55fc6c5ab42c79406d2f41e14b79 /nailgun_launcher
parent95728f6041a32e081a1f4129b8483ef622179b45 (diff)
downloadcbt-8529a70358921af282920c216a81609292c8ba6a.tar.gz
cbt-8529a70358921af282920c216a81609292c8ba6a.tar.bz2
cbt-8529a70358921af282920c216a81609292c8ba6a.zip
Fix exit code trapping across classloaders
A SecurityManager is once installed globally and stays the same across all classloaders. TrapSecurityManager was installed this way, but it looked up the `trapExitCode` in it's own classloader, while classes in other classloaders (when cbt was using another version of cbt) were writing it to their own classloader. This flag needs to be in a global place instead to fix this, so we'll put it straight into the TrapSecurityManager itself.
Diffstat (limited to 'nailgun_launcher')
-rw-r--r--nailgun_launcher/NailgunLauncher.java7
-rw-r--r--nailgun_launcher/Stage0Lib.java10
-rw-r--r--nailgun_launcher/TrapSecurityManager.java52
-rw-r--r--nailgun_launcher/TrappedExitCode.java8
4 files changed, 53 insertions, 24 deletions
diff --git a/nailgun_launcher/NailgunLauncher.java b/nailgun_launcher/NailgunLauncher.java
index 5a70312..37bfa06 100644
--- a/nailgun_launcher/NailgunLauncher.java
+++ b/nailgun_launcher/NailgunLauncher.java
@@ -23,13 +23,6 @@ public class NailgunLauncher{
public final static SecurityManager initialSecurityManager
= System.getSecurityManager();
- public final static ThreadLocal<Boolean> trapExitCode =
- new ThreadLocal<Boolean>() {
- @Override protected Boolean initialValue() {
- return false;
- }
- };
-
public static String TARGET = System.getenv("TARGET");
private static String NAILGUN = "nailgun_launcher/";
private static String STAGE1 = "stage1/";
diff --git a/nailgun_launcher/Stage0Lib.java b/nailgun_launcher/Stage0Lib.java
index 11a9aab..452bdae 100644
--- a/nailgun_launcher/Stage0Lib.java
+++ b/nailgun_launcher/Stage0Lib.java
@@ -20,21 +20,21 @@ public class Stage0Lib{
}
public static int runMain(String cls, String[] args, ClassLoader cl) throws Throwable{
- Boolean trapExitCodeBefore = NailgunLauncher.trapExitCode.get();
+ Boolean trapExitCodeBefore = TrapSecurityManager.trapExitCode().get();
try{
- NailgunLauncher.trapExitCode.set(true);
+ TrapSecurityManager.trapExitCode().set(true);
cl.loadClass(cls)
.getMethod("main", String[].class)
.invoke( null, (Object) args);
return 0;
}catch( InvocationTargetException exception ){
Throwable cause = exception.getCause();
- if(cause instanceof TrappedExitCode){
- return ((TrappedExitCode) cause).exitCode;
+ if(TrapSecurityManager.isTrappedExit(cause)){
+ return TrapSecurityManager.exitCode(cause);
}
throw exception;
} finally {
- NailgunLauncher.trapExitCode.set(trapExitCodeBefore);
+ TrapSecurityManager.trapExitCode().set(trapExitCodeBefore);
}
}
diff --git a/nailgun_launcher/TrapSecurityManager.java b/nailgun_launcher/TrapSecurityManager.java
index fada878..1626787 100644
--- a/nailgun_launcher/TrapSecurityManager.java
+++ b/nailgun_launcher/TrapSecurityManager.java
@@ -9,6 +9,33 @@ would be Nailgun's if running on Nailgun. If we do not delegate to Nailgun, it s
could in some cases kill the server process
*/
public class TrapSecurityManager extends ProxySecurityManager{
+ public static ThreadLocal<Boolean> trapExitCode(){
+ // storing the flag in the installed security manager
+ // instead of e.g. a static member is necessary because
+ // we run multiple versions of CBT with multiple TrapSecurityManager classes
+ // but we need to affect the installed one
+ SecurityManager sm = System.getSecurityManager();
+ if(sm instanceof TrapSecurityManager){
+ return ((TrapSecurityManager) sm)._trapExitCode;
+ } else {
+ try{
+ @SuppressWarnings("unchecked")
+ ThreadLocal<Boolean> res =
+ (ThreadLocal<Boolean>) sm.getClass().getMethod("trapExitCode").invoke(null);
+ return res;
+ } catch(Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ private final ThreadLocal<Boolean> _trapExitCode =
+ new ThreadLocal<Boolean>() {
+ @Override protected Boolean initialValue() {
+ return false;
+ }
+ };
+
public TrapSecurityManager(){
super(NailgunLauncher.initialSecurityManager);
}
@@ -19,21 +46,38 @@ public class TrapSecurityManager extends ProxySecurityManager{
Calling .super leads to ClassNotFound exteption for a lambda.
Calling to the previous SecurityManager leads to a stack overflow
*/
- if(!NailgunLauncher.trapExitCode.get()){
+ if(!TrapSecurityManager.trapExitCode().get()){
super.checkPermission(permission);
}
}
public void checkPermission( Permission permission, Object context ){
/* Does this methods need to be overidden? */
- if(!NailgunLauncher.trapExitCode.get()){
+ if(!TrapSecurityManager.trapExitCode().get()){
super.checkPermission(permission, context);
}
}
+
+ private static final String prefix = "[TrappedExit] ";
+
@Override
public void checkExit( int status ){
- if(NailgunLauncher.trapExitCode.get()){
- throw new TrappedExitCode(status);
+ if(TrapSecurityManager.trapExitCode().get()){
+ // using a RuntimeException and a prefix here instead of a custom
+ // exception type because this is thrown by the installed TrapSecurityManager
+ // but other versions of cbt need to be able to catch it, that do not have access
+ // to that version of the TrapSecurityManager class
+ throw new RuntimeException(prefix+status);
}
super.checkExit(status);
}
+
+ public static boolean isTrappedExit( Throwable t ){
+ return t instanceof RuntimeException && t.getMessage().startsWith(prefix);
+ }
+
+ public static int exitCode( Throwable t ){
+ assert(isTrappedExit(t));
+ return Integer.parseInt( t.getMessage().substring(prefix.length()) );
+ }
+
}
diff --git a/nailgun_launcher/TrappedExitCode.java b/nailgun_launcher/TrappedExitCode.java
deleted file mode 100644
index 154db27..0000000
--- a/nailgun_launcher/TrappedExitCode.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package cbt;
-import java.security.*;
-public class TrappedExitCode extends SecurityException{
- public int exitCode;
- public TrappedExitCode(int exitCode){
- this.exitCode = exitCode;
- }
-}