Skip to content

Commit 33d80ff

Browse files
authored
Merge branch 'master' into JENKINS-70695
2 parents cf5113f + 7b2a76a commit 33d80ff

File tree

7 files changed

+151
-34
lines changed

7 files changed

+151
-34
lines changed

dgm-builder/pom.xml

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,6 @@
2121
</license>
2222
</licenses>
2323

24-
<properties>
25-
<maven.deploy.skip>true</maven.deploy.skip>
26-
</properties>
27-
2824
<build>
2925
<plugins>
3026
<plugin>
@@ -74,19 +70,4 @@
7470
<version>${groovy.version}</version>
7571
</dependency>
7672
</dependencies>
77-
78-
<profiles>
79-
<profile>
80-
<id>skip-installation</id>
81-
<activation>
82-
<property>
83-
<name>set.changelist</name>
84-
<value>true</value>
85-
</property>
86-
</activation>
87-
<properties>
88-
<maven.install.skip>true</maven.install.skip>
89-
</properties>
90-
</profile>
91-
</profiles>
9273
</project>

lib/pom.xml

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,21 @@
2929
<executions>
3030
<execution>
3131
<goals>
32-
<goal>properties</goal>
32+
<goal>copy</goal>
3333
</goals>
34+
<phase>generate-sources</phase>
35+
<configuration>
36+
<artifactItems>
37+
<artifactItem>
38+
<groupId>com.cloudbees</groupId>
39+
<artifactId>groovy-cps-dgm-builder</artifactId>
40+
<version>${project.version}</version>
41+
<classifier>jar-with-dependencies</classifier>
42+
</artifactItem>
43+
</artifactItems>
44+
<outputDirectory>${project.build.directory}</outputDirectory>
45+
<overWriteIfNewer>true</overWriteIfNewer>
46+
</configuration>
3447
</execution>
3548
</executions>
3649
</plugin>
@@ -49,7 +62,7 @@
4962
<executable>java</executable>
5063
<arguments>
5164
<argument>-jar</argument>
52-
<argument>${com.cloudbees:groovy-cps-dgm-builder:jar:jar-with-dependencies}</argument>
65+
<argument>${project.build.directory}/groovy-cps-dgm-builder-${project.version}-jar-with-dependencies.jar</argument>
5366
<argument>${project.build.directory}/generated-sources/dgm</argument>
5467
</arguments>
5568
</configuration>

plugin/pom.xml

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
<dependency>
5252
<groupId>io.jenkins.tools.bom</groupId>
5353
<artifactId>bom-2.361.x</artifactId>
54-
<version>1750.v0071fa_4c4a_e3</version>
54+
<version>1883.vcb_768a_7c3610</version>
5555
<scope>import</scope>
5656
<type>pom</type>
5757
</dependency>
@@ -99,6 +99,10 @@
9999
<groupId>com.github.stephenc.findbugs</groupId>
100100
<artifactId>findbugs-annotations</artifactId>
101101
</exclusion>
102+
<exclusion>
103+
<groupId>io.jenkins.lib</groupId>
104+
<artifactId>support-log-formatter</artifactId>
105+
</exclusion>
102106
</exclusions>
103107
</dependency>
104108
<dependency>
@@ -241,6 +245,16 @@
241245
<groupId>org.jenkins-ci.plugins</groupId>
242246
<artifactId>subversion</artifactId>
243247
<scope>test</scope>
248+
<exclusions>
249+
<exclusion>
250+
<groupId>org.apache.sshd</groupId>
251+
<artifactId>sshd-common</artifactId>
252+
</exclusion>
253+
<exclusion>
254+
<groupId>org.apache.sshd</groupId>
255+
<artifactId>sshd-core</artifactId>
256+
</exclusion>
257+
</exclusions>
244258
</dependency>
245259
<dependency>
246260
<groupId>org.jenkins-ci.plugins</groupId>
@@ -251,7 +265,7 @@
251265
<dependency>
252266
<groupId>org.testcontainers</groupId>
253267
<artifactId>testcontainers</artifactId>
254-
<version>1.17.6</version>
268+
<version>1.18.0</version>
255269
<scope>test</scope>
256270
<exclusions>
257271
<!-- Provided by Jenkins core -->

plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/CpsFlowExecution.java

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,11 @@ private Timing(TimingKind kind) {
426426
}
427427

428428
@Override public void close() {
429-
timings.merge(kind.name(), System.nanoTime() - start, Long::sum);
429+
// Not using ConcurrentHashMap::merge since it can acquire a lock:
430+
long delta = System.nanoTime() - start;
431+
Long prev = timings.get(kind.name());
432+
long nue = prev == null ? delta : prev + delta;
433+
timings.put(kind.name(), nue);
430434
}
431435
}
432436

@@ -557,13 +561,19 @@ private Env createInitialEnv() {
557561

558562
private CpsScript parseScript() throws IOException {
559563
// classloader hierarchy. See doc/classloader.md
560-
trusted = new CpsGroovyShellFactory(this).forTrusted().build();
561-
shell = new CpsGroovyShellFactory(this).withParent(trusted).build();
564+
CpsScript s;
565+
try {
566+
trusted = new CpsGroovyShellFactory(this).forTrusted().build();
567+
shell = new CpsGroovyShellFactory(this).withParent(trusted).build();
562568

563-
CpsScript s = (CpsScript) shell.reparse("WorkflowScript",script);
569+
s = (CpsScript) shell.reparse("WorkflowScript",script);
564570

565-
for (Entry<String, String> e : loadedScripts.entrySet()) {
566-
shell.reparse(e.getKey(), e.getValue());
571+
for (Entry<String, String> e : loadedScripts.entrySet()) {
572+
shell.reparse(e.getKey(), e.getValue());
573+
}
574+
} catch (RuntimeException | Error x) {
575+
closeShells();
576+
throw x;
567577
}
568578

569579
s.execution = this;
@@ -1261,7 +1271,13 @@ public static void maybeAutoPersistNode(@NonNull FlowNode node) {
12611271

12621272
@Override
12631273
public boolean isComplete() {
1264-
return done || super.isComplete();
1274+
if (done) {
1275+
return true;
1276+
} else {
1277+
synchronized (this) {
1278+
return heads != null && super.isComplete();
1279+
}
1280+
}
12651281
}
12661282

12671283
/**
@@ -1304,10 +1320,26 @@ synchronized void onProgramEnd(Outcome outcome) {
13041320
this.persistedClean = Boolean.TRUE;
13051321
}
13061322

1323+
private void closeShells() {
1324+
try {
1325+
if (shell != null) {
1326+
LOGGER.fine(() -> "closing main class loader from " + owner);
1327+
shell.getClassLoader().close();
1328+
shell = null;
1329+
}
1330+
if (trusted != null) {
1331+
LOGGER.fine(() -> "closing trusted class loader from " + owner);
1332+
trusted.getClassLoader().close();
1333+
trusted = null;
1334+
}
1335+
} catch (IOException x) {
1336+
LOGGER.log(Level.WARNING, "failed to close class loaders from " + owner, x);
1337+
}
1338+
}
1339+
13071340
void cleanUpHeap() {
13081341
LOGGER.log(Level.FINE, "cleanUpHeap on {0}", owner);
1309-
shell = null;
1310-
trusted = null;
1342+
closeShells();
13111343
if (scriptClass != null) {
13121344
try {
13131345
cleanUpLoader(scriptClass.getClassLoader(), new HashSet<>(), new HashSet<>());
@@ -1694,6 +1726,7 @@ public void pause(final boolean v) throws IOException {
16941726
LOGGER.log(Level.WARNING, null, t);
16951727
}
16961728
});
1729+
cpsExec.getOwner().getListener().getLogger().close();
16971730
}
16981731
} catch (Exception ex) {
16991732
LOGGER.log(Level.WARNING, "Error persisting Pipeline execution at shutdown: "+((CpsFlowExecution) execution).owner, ex);

plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/CpsGroovyShell.java

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@
1414
import java.util.logging.Logger;
1515
import edu.umd.cs.findbugs.annotations.CheckForNull;
1616
import edu.umd.cs.findbugs.annotations.NonNull;
17+
import java.io.File;
18+
import java.io.InputStream;
19+
import java.net.MalformedURLException;
20+
import java.net.URI;
21+
import java.net.URLConnection;
22+
import java.net.URLStreamHandler;
23+
import java.util.regex.Matcher;
24+
import java.util.regex.Pattern;
1725
import org.codehaus.groovy.control.CompilationFailedException;
1826
import org.codehaus.groovy.control.CompilationUnit;
1927
import org.codehaus.groovy.control.CompilerConfiguration;
@@ -76,6 +84,46 @@ private static final class CleanGroovyClassLoader extends GroovyClassLoader {
7684
return new CleanClassCollector(unit, su);
7785
}
7886

87+
private static final Pattern JAR_URL = Pattern.compile("jar:(file:/.+[.]jar)!/.+");
88+
89+
// Avoid expensive and (JDK-6956385) leaky implementations of certain JarURLConnection methods:
90+
@Override public URL findResource(String name) {
91+
URL url = super.findResource(name);
92+
if (url != null && url.getProtocol().equals("jar")) {
93+
try {
94+
return new URL(url.getProtocol(), url.getHost(), url.getPort(), url.getFile(), new URLStreamHandler() {
95+
@Override protected URLConnection openConnection(URL url2) throws IOException {
96+
URLConnection delegate = url.openConnection();
97+
return new URLConnection(url2) {
98+
@Override public void connect() throws IOException {
99+
delegate.connect();
100+
}
101+
@Override public InputStream getInputStream() throws IOException {
102+
return delegate.getInputStream();
103+
}
104+
@Override public String getHeaderField(String name) {
105+
return delegate.getHeaderField(name);
106+
}
107+
@Override public long getLastModified() {
108+
Matcher m = JAR_URL.matcher(url.toString());
109+
if (m.matches()) {
110+
return new File(URI.create(m.group(1))).lastModified();
111+
}
112+
return delegate.getLastModified();
113+
}
114+
@Override public String getContentEncoding() {
115+
return null;
116+
}
117+
};
118+
}
119+
});
120+
} catch (MalformedURLException x) {
121+
LOGGER.log(Level.WARNING, null, x);
122+
}
123+
}
124+
return url;
125+
}
126+
79127
private final class CleanClassCollector extends ClassCollector {
80128

81129
CleanClassCollector(CompilationUnit unit, SourceUnit su) {

plugin/src/test/java/org/jenkinsci/plugins/workflow/cps/CpsFlowDefinitionRJRTest.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
package org.jenkinsci.plugins.workflow.cps;
22

3+
import hudson.Functions;
4+
import java.util.logging.Level;
35
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
6+
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
7+
import org.junit.Assume;
48
import org.junit.Rule;
59
import org.junit.Test;
610
import org.jvnet.hudson.test.JenkinsRule;
@@ -21,4 +25,28 @@ private static void doesItSmoke(JenkinsRule r) throws Exception {
2125
p.setDefinition(new CpsFlowDefinition("print Jenkins.get().getRootDir().toString()", false));
2226
r.assertBuildStatusSuccess(p.scheduleBuild2(0));
2327
}
28+
29+
@Test
30+
public void flushLogsOnShutdown() throws Throwable {
31+
Assume.assumeFalse("RealJenkinsRule does not shut down Jenkins cleanly on Windows, see https://github.com/jenkinsci/jenkins-test-harness/pull/559", Functions.isWindows());
32+
rjr.withLogger(CpsFlowExecution.class, Level.FINER);
33+
rjr.then(CpsFlowDefinitionRJRTest::flushLogsOnShutdownPreRestart);
34+
rjr.then(CpsFlowDefinitionRJRTest::flushLogsOnShutdownPostRestart);
35+
}
36+
37+
private static void flushLogsOnShutdownPreRestart(JenkinsRule r) throws Exception {
38+
WorkflowJob p = r.createProject(WorkflowJob.class, "p");
39+
p.setDefinition(new CpsFlowDefinition("sleep 10\n", true));
40+
WorkflowRun b = p.scheduleBuild2(0).waitForStart();
41+
r.waitForMessage("Sleeping for 10 sec", b);
42+
r.jenkins.doQuietDown();
43+
}
44+
45+
private static void flushLogsOnShutdownPostRestart(JenkinsRule r) throws Exception {
46+
WorkflowJob p = r.jenkins.getItemByFullName("p", WorkflowJob.class);
47+
WorkflowRun b = p.getLastBuild();
48+
r.assertBuildStatusSuccess(r.waitForCompletion(b));
49+
r.assertLogContains("Resuming build at ", b);
50+
r.assertLogContains("Pausing (Preparing for shutdown)", b);
51+
}
2452
}

pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
<parent>
55
<groupId>org.jenkins-ci.plugins</groupId>
66
<artifactId>plugin</artifactId>
7-
<version>4.54</version>
8-
<relativePath />
7+
<version>4.59</version>
8+
<relativePath/>
99
</parent>
1010
<groupId>org.jenkins-ci.plugins.workflow</groupId>
1111
<artifactId>workflow-cps-parent</artifactId>

0 commit comments

Comments
 (0)