[JENKINS-60449] Attempt to fix an odd case of OptionalExtension blowing up Jenkins (#4393)

* Add new module optional-depender and a new failing test

* Variant plugin is a dependency of optional-depender

Optional-depender contains the following class

@OptionalExtension(requirePlugins = {"dependee"})
public class OptionalDependerExtension {
      private static void foo(Dependee d) {

      }
}

* [JENKINS-60449] Move plugin initialization at the end, keep only one extension refresh

* Improve logic to detect classloading issues

Inspect all declared constructors/methods/fields recursively to exclude
failing classes from Guice rather than have Guice explode.

This also fix the failing test, but the previous commit is still better
because it avoids an extra Jenkins.get().refreshExtensions() call.

* Only test resolveClass method if the classloader is not the bootstrap one
This commit is contained in:
Vincent Latombe authored and Oleg Nenashev committed 2020-01-03 23:26:35 +01:00
1 parent 5d78705806
commit dd59e8c11c
5 files changed
+65 -35

No files matched your search

+14 -17
View File
@@ -949,23 +949,6 @@ public abstract class PluginManager extends AbstractModelObject implements OnMas
@Restricted(NoExternalUse.class)
public void start(List<PluginWrapper> plugins) throws Exception {
try (ACLContext context = ACL.as(ACL.SYSTEM)) {
Jenkins.get().refreshExtensions();
for (PluginWrapper p : plugins) {
p.getPlugin().postInitialize();
}
// run initializers in the added plugins
Reactor r = new Reactor(InitMilestone.ordering());
Set<ClassLoader> loaders = plugins.stream().map(p -> p.classLoader).collect(Collectors.toSet());
r.addAll(new InitializerFinder(uberClassLoader) {
@Override
protected boolean filter(Method e) {
return !loaders.contains(e.getDeclaringClass().getClassLoader()) || super.filter(e);
}
}.discoverTasks(r));
new InitReactorRunner().run(r);
Map<String, PluginWrapper> pluginsByName = plugins.stream().collect(Collectors.toMap(p -> p.getShortName(), p -> p));
// recalculate dependencies of plugins optionally depending the newly deployed ones.
@@ -993,6 +976,20 @@ public abstract class PluginManager extends AbstractModelObject implements OnMas
} catch (ExtensionRefreshException e) {
throw new IOException("Failed to refresh extensions after installing some plugins", e);
}
for (PluginWrapper p : plugins) {
p.getPlugin().postInitialize();
}
// run initializers in the added plugins
Reactor r = new Reactor(InitMilestone.ordering());
Set<ClassLoader> loaders = plugins.stream().map(p -> p.classLoader).collect(Collectors.toSet());
r.addAll(new InitializerFinder(uberClassLoader) {
@Override
protected boolean filter(Method e) {
return !loaders.contains(e.getDeclaringClass().getClassLoader()) || super.filter(e);
}
}.discoverTasks(r));
new InitReactorRunner().run(r);
}
}