From ae479e1abf3f9f6cb26a67848dba8d67f34fc682 Mon Sep 17 00:00:00 2001 From: Vincent Latombe Date: Fri, 18 Oct 2024 17:27:33 +0200 Subject: [PATCH] If an exception occurs while launching an agent, the underlying connection and session should be closed Observed the following stacktrace when running a controller using JDK17 bytecode level, and having an agent template still configured with a JDK11. The agent initially connects fine, however as soon as it attempts to do remote classloading, it fails. As it occurs while setting up the hudson.remoting.Channel itself, the listener that is registered during initialization is never called, and the exception handling block should instead close the underlying resources. 2024-10-18 02:48:21.686+0000 [id=593] WARNING c.g.j.p.c.ComputeEngineCloud#log: Error: java.lang.UnsupportedClassVersionError: hudson/slaves/SlaveComputer$SlaveVersion has been compiled by a more recent version of the Java Runtime (class file version 61.0), this version of the Java Runtime only recognizes class file versions up to 55.0 at java.base/java.lang.ClassLoader.defineClass1(Native Method) at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1017) at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:878) at hudson.remoting.RemoteClassLoader.loadClassFile(RemoteClassLoader.java:470) Also: hudson.remoting.Channel$CallSiteStackTrace: Remote call to gce-cloud-gauntlet3-gaia-jdk11-t4dx04 at hudson.remoting.Channel.attachCallSiteStackTrace(Channel.java:1923) at hudson.remoting.UserRequest$ExceptionResponse.retrieve(UserRequest.java:384) at hudson.remoting.Channel.call(Channel.java:1112) at hudson.slaves.SlaveComputer.setChannel(SlaveComputer.java:663) at hudson.slaves.SlaveComputer.setChannel(SlaveComputer.java:441) at PluginClassLoader for google-compute-engine//com.google.jenkins.plugins.computeengine.ComputeEngineComputerLauncher.launch(ComputeEngineComputerLauncher.java:303) at PluginClassLoader for google-compute-engine//com.google.jenkins.plugins.computeengine.ComputeEngineComputerLauncher.launch(ComputeEngineComputerLauncher.java:214) at hudson.slaves.SlaveComputer.lambda$_connect$0(SlaveComputer.java:297) at jenkins.util.ContextResettingExecutorService$2.call(ContextResettingExecutorService.java:46) at jenkins.security.ImpersonatingExecutorService$2.call(ImpersonatingExecutorService.java:80) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) at java.base/java.lang.Thread.run(Thread.java:840) Caused: java.lang.UnsupportedClassVersionError: Failed to load hudson.slaves.SlaveComputer$SlaveVersion at hudson.remoting.RemoteClassLoader.loadClassFile(RemoteClassLoader.java:472) at hudson.remoting.RemoteClassLoader.loadRemoteClass(RemoteClassLoader.java:301) at hudson.remoting.RemoteClassLoader.loadWithMultiClassLoader(RemoteClassLoader.java:277) at hudson.remoting.RemoteClassLoader.findClass(RemoteClassLoader.java:236) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:589) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522) at java.base/java.lang.Class.forName0(Native Method) at java.base/java.lang.Class.forName(Class.java:398) at hudson.remoting.MultiClassLoaderSerializer$Input.resolveClass(MultiClassLoaderSerializer.java:133) at java.base/java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:2003) at java.base/java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1870) at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2201) at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1687) at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:489) at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:447) at hudson.remoting.UserRequest.deserialize(UserRequest.java:312) at hudson.remoting.UserRequest.perform(UserRequest.java:196) at hudson.remoting.UserRequest.perform(UserRequest.java:50) at hudson.remoting.Request$2.run(Request.java:391) at hudson.remoting.InterceptingExecutorService.lambda$wrap$0(InterceptingExecutorService.java:81) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) at java.base/java.lang.Thread.run(Thread.java:829) Caused: java.io.IOException: Remote call on gce-cloud-gauntlet3-gaia-jdk11-t4dx04 failed at hudson.remoting.Channel.call(Channel.java:1116) at hudson.slaves.SlaveComputer.setChannel(SlaveComputer.java:663) at hudson.slaves.SlaveComputer.setChannel(SlaveComputer.java:441) at PluginClassLoader for google-compute-engine//com.google.jenkins.plugins.computeengine.ComputeEngineComputerLauncher.launch(ComputeEngineComputerLauncher.java:303) at PluginClassLoader for google-compute-engine//com.google.jenkins.plugins.computeengine.ComputeEngineComputerLauncher.launch(ComputeEngineComputerLauncher.java:214) at hudson.slaves.SlaveComputer.lambda$_connect$0(SlaveComputer.java:297) at jenkins.util.ContextResettingExecutorService$2.call(ContextResettingExecutorService.java:46) at jenkins.security.ImpersonatingExecutorService$2.call(ImpersonatingExecutorService.java:80) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) at java.base/java.lang.Thread.run(Thread.java:840) --- .../ComputeEngineComputerLauncher.java | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/google/jenkins/plugins/computeengine/ComputeEngineComputerLauncher.java b/src/main/java/com/google/jenkins/plugins/computeengine/ComputeEngineComputerLauncher.java index fcc93fb5..b0b0be1c 100644 --- a/src/main/java/com/google/jenkins/plugins/computeengine/ComputeEngineComputerLauncher.java +++ b/src/main/java/com/google/jenkins/plugins/computeengine/ComputeEngineComputerLauncher.java @@ -280,10 +280,11 @@ private void launch(ComputeEngineComputer computer, TaskListener listener) { return; } - final Connection conn; + Connection conn = null; Optional cleanupConn; PrintStream logger = listener.getLogger(); logInfo(computer, listener, "Launching instance: " + node.getNodeName()); + Session sess = null; try { cleanupConn = setupConnection(node, computer, listener); if (!cleanupConn.isPresent()) { @@ -298,16 +299,24 @@ private void launch(ComputeEngineComputer computer, TaskListener listener) { copyAgentJar(computer, conn, listener, jenkinsDir); String launchString = getJavaLaunchString(javaExecPath, jenkinsDir); logInfo(computer, listener, "Launching Jenkins agent via plugin SSH: " + launchString); - final Session sess = conn.openSession(); + sess = conn.openSession(); sess.execCommand(launchString); + Session finalSess = sess; + Connection finalConn = conn; computer.setChannel(sess.getStdout(), sess.getStdin(), logger, new Channel.Listener() { @Override public void onClosed(Channel channel, IOException cause) { - sess.close(); - conn.close(); + finalSess.close(); + finalConn.close(); } }); } catch (Exception e) { + if (sess != null) { + sess.close(); + } + if (conn != null) { + conn.close(); + } logException(computer, listener, "Error: ", e); } }