Navigation Menu

Skip to content

Commit

Permalink
[JENKINS-19445] Force class load on UserRequest (#82)
Browse files Browse the repository at this point in the history
* Force class load on UserRequest, see JENKINS-19445

This is a workaround to force class load of any class. This helps prevent deadlock on windows nodes when using JNA and Subversion.
Use property hudson.remoting.RemoteClassLoader.force to name the class to load. Ideally this forced load should happen earlier on the startup, however the classloader isn't available.

* Update UserRequest as per code review comments

Fixes based on code review of pull-request: #82

* Fix Logger.log() invocation

Fix Logger.log() invocation: needs Object[], not vargs.
  • Loading branch information
jenkins-bbva authored and oleg-nenashev committed May 9, 2016
1 parent f4d2876 commit 8e0a866
Showing 1 changed file with 32 additions and 0 deletions.
32 changes: 32 additions & 0 deletions src/main/java/hudson/remoting/UserRequest.java
Expand Up @@ -34,6 +34,8 @@
import java.io.Serializable;
import java.io.NotSerializableException;
import java.io.ObjectInputStream;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
* {@link Request} that can take {@link Callable} whose actual implementation
Expand Down Expand Up @@ -86,10 +88,40 @@ public UserRequest(Channel local, Callable<?,EXC> c) throws IOException {
return result;
}

private static boolean workaroundDone = false;
protected UserResponse<RSP,EXC> perform(Channel channel) throws EXC {
try {
ClassLoader cl = channel.importedClassLoaders.get(classLoaderProxy);

// Allow forcibly load of a class, allows to workaround:
// @See https://issues.jenkins-ci.org/browse/JENKINS-19445
// @Related https://issues.tmatesoft.com/issue/SGT-451
final String clazz = System.getProperty(RemoteClassLoader.class.getName() + ".force", null);
if ( clazz != null && !workaroundDone) {
// Optimistic logging set.
String eventMsg = "Loaded";
Level logLevel = Level.INFO;
// java.lang classes can only be instantiated by the bootstrap Classloader.
// Guarantees that *all* threads with whatever Classloader in use, have the
// same mutex instance: an intance of java.lang.Class<java.lang.Object>
synchronized(java.lang.Object.class)
{
workaroundDone = true;
try {
final Class<?> loaded = Class.forName( clazz, true, cl );
} catch (final ClassNotFoundException cnfe) {
// not big deal, elevate log to warning and swallow exception
eventMsg = "Couldn't find";
logLevel = Level.WARNING;
}
}
final Logger logger = Logger.getLogger(RemoteClassLoader.class.getName());
if( logger.isLoggable(logLevel) )
{
logger.log(logLevel, "%s class '%s' using classloader: %s", new String[]{ eventMsg, clazz, cl.toString()} );
}
}

RSP r = null;
Channel oldc = Channel.setCurrent(channel);
try {
Expand Down

0 comments on commit 8e0a866

Please sign in to comment.