-
Bug
-
Resolution: Fixed
-
Major
FingerprintAction has the following field:
private final AbstractBuild build;
This field links to an AbstractBuild, which in turn has the following field:
protected transient final JobT project;
Once Jenkin persists a run to a file, the build from the FingerprintAction will be saved, but the project itself will not get saved. An example fragment from one of the build files looks like this:
<hudson.tasks.Fingerprinter_-FingerprintAction> <build class="build"> <actions> <hudson.model.ParametersAction reference="../../../../hudson.model.ParametersAction"/> <hudson.model.CauseAction reference="../../../../hudson.model.CauseAction"/> <hudson.plugins.copyartifact.CopyArtifact_-EnvAction reference="../../../../hudson.plugins.copyartifact.CopyArtifact_-EnvAction"/> <hudson.tasks.Fingerprinter_-FingerprintAction reference="../../.."/> </actions> <number>17</number> <startTime>1358250655935</startTime> <result>SUCCESS</result> <duration>4488</duration> <charset>UTF-8</charset> <keepLog>false</keepLog> <builtOn></builtOn> <workspace>/opt/hudson/files/jobs/Deploy/workspace</workspace> <hudsonVersion>1.494</hudsonVersion> <scm class="hudson.scm.NullChangeLogParser"/> <culprits class="com.google.common.collect.EmptyImmutableSortedSet"/> </build> ...
When the files are read and the objects are created, the project field remains empty. During intialization, the onLoad() method is called:
@Override protected R retrieve(File d) throws IOException { if(new File(d,"build.xml").exists()) { // if the build result file isn't in the directory, ignore it. try { R b = cons.create(d); b.onLoad(); if (LOGGER.isLoggable(FINE)) LOGGER.log(FINE,"Loaded " + b.getFullDisplayName(),new ThisIsHowItsLoaded()); return b; } catch (IOException e) { LOGGER.log(Level.WARNING, "could not load " + d, e); } catch (InstantiationError e) { LOGGER.log(Level.WARNING, "could not load " + d, e); } } return null; }
This method invokes onLoad() on all actions that implement RunAction:
for (Action a : getActions()) if (a instanceof RunAction) ((RunAction) a).onLoad();
The FingerprintAction does implement the RunAction interface, and the method is implemented as follows:
public void onLoad() { // share data structure with nearby builds, but to keep lazy loading efficient, // don't go back the history forever. if (rand.nextInt(2)!=0) { Run pb = build.getPreviousBuild(); if (pb!=null) { FingerprintAction a = pb.getAction(FingerprintAction.class); if (a!=null) compact(a); } } }
Build is set, so getPreviousBuild() can be called, this will however fail because the project is null (due to the transient field) and will throw a NullPointerException.
This causes very strange behavior as sometimes pages are working, sometimes they are not. There are a lot of stack traces around that actually look like as if they were caused by the same problem, for example: https://issues.jenkins-ci.org/browse/JENKINS-16845
Stack Trace looks like this:
Caused by: java.lang.NullPointerException at hudson.model.AbstractBuild.getPreviousBuild(AbstractBuild.java:207) at hudson.tasks.Fingerprinter$FingerprintAction.onLoad(Fingerprinter.java:349) at hudson.model.Run.onLoad(Run.java:315) at hudson.model.RunMap.retrieve(RunMap.java:221) at hudson.model.RunMap.retrieve(RunMap.java:59) at jenkins.model.lazy.AbstractLazyLoadRunMap.load(AbstractLazyLoadRunMap.java:638) at jenkins.model.lazy.AbstractLazyLoadRunMap.load(AbstractLazyLoadRunMap.java:601) at jenkins.model.lazy.AbstractLazyLoadRunMap.search(AbstractLazyLoadRunMap.java:344) at hudson.model.AbstractBuild.getPreviousBuild(AbstractBuild.java:207) at hudson.model.AbstractBuild.getPreviousBuild(AbstractBuild.java:100) at hudson.model.RunMap$1.next(RunMap.java:107) at hudson.model.RunMap$1.next(RunMap.java:96) at hudson.widgets.HistoryWidget.getRenderList(HistoryWidget.java:133) ... 122 more
- is duplicated by
-
JENKINS-16845 NullPointer in getPreviousBuild
-
- Resolved
-
- is related to
-
JENKINS-18410 Use RunAction2 from TestResultAction
-
- Resolved
-
-
JENKINS-18411 Use RunAction2 from EnvInjectPluginAction
-
- Resolved
-
-
JENKINS-20950 NPE during Discard Old Data
-
- Resolved
-
- relates to
-
JENKINS-43218 Discard Unreadable Data leads to NPE in TreeMap.putAll
-
- Resolved
-
-
JENKINS-45892 Forbid nested references to model objects
-
- Resolved
-
We got or have XML files (build.xml) like the one you showed very often, however, there is a small number of build.xml files that looks like the one that I described. Isn't that related to how the whole memory object tree get's serialized to the file and also depends on whether the same objects are used or not to represent the builds?
However, after we fixed the code the way I described, we never faced the issue again and Jenkins is working like charm now. We had the following issues before: