forked from jenkinsci/workflow-job-plugin
-
Notifications
You must be signed in to change notification settings - Fork 1
Address how and where we end the AsynchronousExecution #3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
svanoort
wants to merge
7
commits into
jglick:logs-JENKINS-38381
from
svanoort:logs-JENKINS-38381-fixed
Closed
Changes from 3 commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
d08949e
First hack at correcting the completion of the AsynchronousExecution
svanoort 877dafd
Findbugs fix
svanoort c6bd9b0
Fixes to completion logic
svanoort e807997
Remove some pieces that are not strictly required to see if they trig…
svanoort bfc87ff
One final attempt to debug why lazy loading is not lazy
svanoort 330a2af
hardening testcases against timing quirks
svanoort d24752d
Revert "One final attempt to debug why lazy loading is not lazy"
svanoort File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -181,7 +181,7 @@ public String url() { | |
| * Flag for whether or not the build has completed somehow. | ||
| * This was previously a transient field, so we may need to recompute in {@link #onLoad} based on {@link FlowExecution#isComplete}. | ||
| */ | ||
| Boolean completed; // Non-private for testing | ||
| volatile Boolean completed; // Non-private for testing | ||
|
|
||
| /** Protects the access to logsToCopy, completed, and branchNameCache that are used in the logCopy process */ | ||
| private transient Object logCopyGuard = new Object(); | ||
|
|
@@ -508,7 +508,7 @@ private String key() { | |
| new XmlFile(XSTREAM,new File(getRootDir(),"build.xml")).unmarshal(this); | ||
| } | ||
|
|
||
| @Override protected void onLoad() { | ||
| @Override protected void onLoad() { // Here there be DRAGONS: due to lazy-loading and subtle threading risks, be very cautious! | ||
| try { | ||
| synchronized (getLogCopyGuard()) { | ||
| if (executionLoaded) { | ||
|
|
@@ -543,8 +543,10 @@ private String key() { | |
| } | ||
| } else { // Execution nulled due to a critical failure, explicitly mark completed | ||
| completed = Boolean.TRUE; | ||
| needsToPersist = true; // Make sure we save toggled state | ||
| } | ||
| } else if (execution == null) { | ||
| } else if (execution == null && completed != Boolean.TRUE) { | ||
| needsToPersist = true; // Make sure we save toggled state | ||
| completed = Boolean.TRUE; | ||
| } | ||
| if (needsToPersist && completed) { | ||
|
|
@@ -572,6 +574,20 @@ private String key() { | |
| } | ||
| } | ||
|
|
||
| private void endExecutionTask() { | ||
| try { | ||
| Executor executor = getExecutor(); | ||
| if (executor != null) { | ||
| AsynchronousExecution asynchronousExecution = executor.getAsynchronousExecution(); | ||
| if (asynchronousExecution != null) { | ||
| asynchronousExecution.completed(null); | ||
| } | ||
| } | ||
| } catch (Exception ex) { | ||
| LOGGER.log(Level.WARNING, "Error when trying to end the FlyWeightTask for run "+this, ex); | ||
| } | ||
| } | ||
|
|
||
| /** Handles normal build completion (including errors) but also handles the case that the flow did not even start correctly, for example due to an error in {@link FlowExecution#start}. */ | ||
| private void finish(@Nonnull Result r, @CheckForNull Throwable t) { | ||
| boolean nullListener = false; | ||
|
|
@@ -580,6 +596,7 @@ private void finish(@Nonnull Result r, @CheckForNull Throwable t) { | |
| setResult(r); | ||
| completed = Boolean.TRUE; | ||
| duration = Math.max(0, System.currentTimeMillis() - getStartTimeInMillis()); | ||
|
|
||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. could revert |
||
| } | ||
| try { | ||
| LOGGER.log(Level.INFO, "{0} completed: {1}", new Object[]{toString(), getResult()}); | ||
|
|
@@ -605,7 +622,8 @@ private void finish(@Nonnull Result r, @CheckForNull Throwable t) { | |
| } | ||
| listener = null; | ||
| } | ||
| saveWithoutFailing(); // TODO useless if we are inside a BulkChange | ||
| saveWithoutFailing(); | ||
| endExecutionTask(); | ||
| Timer.get().submit(() -> { | ||
| try { | ||
| getParent().logRotate(); | ||
|
|
@@ -614,7 +632,8 @@ private void finish(@Nonnull Result r, @CheckForNull Throwable t) { | |
| } | ||
| }); | ||
| onEndBuilding(); | ||
| } finally { // Ensure this is ALWAYS removed from FlowExecutionList | ||
| } finally { // Ensure this is ALWAYS removed from FlowExecutionList and finished | ||
| endExecutionTask(); // Just in case an exception was thrown above | ||
| FlowExecutionList.get().unregister(new Owner(this)); | ||
| } | ||
|
|
||
|
|
@@ -1109,8 +1128,9 @@ private void saveWithoutFailing() { | |
|
|
||
| @Override | ||
| public void save() throws IOException { | ||
|
|
||
| if(BulkChange.contains(this)) return; | ||
| /* Checking for completion ensures the final save can complete. | ||
| */ | ||
| if(BulkChange.contains(this) && completed != Boolean.TRUE) return; | ||
| File loc = new File(getRootDir(),"build.xml"); | ||
| XmlFile file = new XmlFile(XSTREAM,loc); | ||
|
|
||
|
|
@@ -1121,23 +1141,9 @@ public void save() throws IOException { | |
| isAtomic = hint.isAtomicWrite(); | ||
| } | ||
|
|
||
| boolean completeAsynchronousExecution = false; | ||
| try { | ||
| synchronized (this) { | ||
| completeAsynchronousExecution = Boolean.TRUE.equals(completed); | ||
| PipelineIOUtils.writeByXStream(this, loc, XSTREAM2, isAtomic); | ||
| SaveableListener.fireOnChange(this, file); | ||
| } | ||
| } finally { | ||
| if (completeAsynchronousExecution) { | ||
| Executor executor = getExecutor(); | ||
| if (executor != null) { | ||
| AsynchronousExecution asynchronousExecution = executor.getAsynchronousExecution(); | ||
| if (asynchronousExecution != null) { | ||
| asynchronousExecution.completed(null); | ||
| } | ||
| } | ||
| } | ||
| synchronized (this) { | ||
| PipelineIOUtils.writeByXStream(this, loc, XSTREAM2, isAtomic); | ||
| SaveableListener.fireOnChange(this, file); | ||
| } | ||
| } | ||
| } | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not really related to changes in JEP-210, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not as such, but more correcting for some issues in the logic.