Fix [JENKINS-49206] by ensuring Timer threads get standard classloader (#3272)

* Fix [JENKINS-49206] by ensuring Timer threads get standard classloader

* Refactor to better fit in with existing ThreadFactor utils

* Fix javadocs
This commit is contained in:
Sam Van Oort authored and Oleg Nenashev committed 2018-02-03 13:22:53 +01:00
1 parent 6cefcf17a8
commit 2a6fc653ee
3 files changed
+84 -2

No files matched your search

@@ -1,12 +1,18 @@
package jenkins.util;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import groovy.lang.GroovyClassLoader;
import hudson.triggers.SafeTimerTask;
import org.junit.Assert;
import org.junit.Test;
import org.jvnet.hudson.test.Issue;
import java.net.URLClassLoader;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
public class TimerTest {
@@ -44,4 +50,52 @@ public class TimerTest {
}
}
/**
* Launch two tasks which can only complete
* by running doRun() concurrently.
*/
@Test
@Issue("JENKINS-49206")
public void timerBogusClassloader() throws Exception {
final int threadCount = 10; // Twice Timer pool size to ensure we end up creating at least one new thread
final CountDownLatch startLatch = new CountDownLatch(threadCount);
final ClassLoader[] contextClassloaders = new ClassLoader[threadCount];
ScheduledFuture[] futures = new ScheduledFuture[threadCount];
final ClassLoader bogusClassloader = new GroovyClassLoader();
Runnable timerTest = new Runnable() {
@Override
public void run() {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(bogusClassloader);
ScheduledExecutorService exec = Timer.get();
for (int i=0; i<threadCount; i++) {
final int j = i;
futures[j] = exec.schedule(new Runnable() {
@Override
public void run() {
try {
startLatch.countDown();
contextClassloaders[j] = Thread.currentThread().getContextClassLoader();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
}, 0, TimeUnit.SECONDS);
}
Thread.currentThread().setContextClassLoader(cl);
}
};
Thread t = new Thread(timerTest);
t.run();
t.join(1000L);
for (int i=0; i<threadCount; i++) {
futures[i].get();
Assert.assertEquals(Timer.class.getClassLoader(), contextClassloaders[i]);
}
}
}