|
@@ -135,6 +135,8 @@ |
|
|
import hudson.model.Computer; |
|
|
import hudson.security.AccessControlled; |
|
|
import hudson.util.VersionNumber; |
|
|
|
|
|
import javax.annotation.Nonnull; |
|
|
import java.io.UnsupportedEncodingException; |
|
|
import java.nio.charset.Charset; |
|
|
import static java.util.logging.Level.*; |
|
@@ -1366,79 +1368,81 @@ public void afterDisconnect(SlaveComputer slaveComputer, final TaskListener list |
|
|
srv.shutdown(); |
|
|
} |
|
|
|
|
|
synchronized (this) { |
|
|
if (connection != null) { |
|
|
boolean connectionLost = reportTransportLoss(connection, listener); |
|
|
if (session != null) { |
|
|
// give the process 3 seconds to write out its dying message before we cut the loss |
|
|
// and give up on this process. if the slave process had JVM crash, OOME, or any other |
|
|
// critical problem, this will allow us to capture that. |
|
|
// exit code is also an useful info to figure out why the process has died. |
|
|
try { |
|
|
listener.getLogger().println(getSessionOutcomeMessage(session, connectionLost)); |
|
|
session.getStdout().close(); |
|
|
session.close(); |
|
|
} catch (Throwable t) { |
|
|
t.printStackTrace(listener.error(Messages.SSHLauncher_ErrorWhileClosingConnection())); |
|
|
} |
|
|
session = null; |
|
|
tearDownConnection(slaveComputer, listener); |
|
|
} |
|
|
|
|
|
private synchronized void tearDownConnection(@Nonnull SlaveComputer slaveComputer, @Nonnull TaskListener listener) { |
|
|
if (connection != null) { |
|
|
boolean connectionLost = reportTransportLoss(connection, listener); |
|
|
if (session != null) { |
|
|
// give the process 3 seconds to write out its dying message before we cut the loss |
|
|
// and give up on this process. if the slave process had JVM crash, OOME, or any other |
|
|
// critical problem, this will allow us to capture that. |
|
|
// exit code is also an useful info to figure out why the process has died. |
|
|
try { |
|
|
listener.getLogger().println(getSessionOutcomeMessage(session, connectionLost)); |
|
|
session.getStdout().close(); |
|
|
session.close(); |
|
|
} catch (Throwable t) { |
|
|
t.printStackTrace(listener.error(Messages.SSHLauncher_ErrorWhileClosingConnection())); |
|
|
} |
|
|
session = null; |
|
|
} |
|
|
|
|
|
Slave n = slaveComputer.getNode(); |
|
|
if (n != null && !connectionLost) { |
|
|
String workingDirectory = getWorkingDirectory(n); |
|
|
final String fileName = workingDirectory + "/slave.jar"; |
|
|
Future<?> tidyUp = Computer.threadPoolForRemoting.submit(new Runnable() { |
|
|
public void run() { |
|
|
// this would fail if the connection is already lost, so we want to check that. |
|
|
// TODO: Connection class should expose whether it is still connected or not. |
|
|
|
|
|
SFTPv3Client sftpClient = null; |
|
|
try { |
|
|
sftpClient = new SFTPv3Client(connection); |
|
|
sftpClient.rm(fileName); |
|
|
} catch (Exception e) { |
|
|
if (sftpClient == null) {// system without SFTP |
|
|
try { |
|
|
connection.exec("rm " + fileName, listener.getLogger()); |
|
|
} catch (Error error) { |
|
|
throw error; |
|
|
} catch (Throwable x) { |
|
|
x.printStackTrace(listener.error(Messages.SSHLauncher_ErrorDeletingFile(getTimestamp()))); |
|
|
// We ignore other Exception types |
|
|
} |
|
|
} else { |
|
|
e.printStackTrace(listener.error(Messages.SSHLauncher_ErrorDeletingFile(getTimestamp()))); |
|
|
} |
|
|
} finally { |
|
|
if (sftpClient != null) { |
|
|
sftpClient.close(); |
|
|
Slave n = slaveComputer.getNode(); |
|
|
if (n != null && !connectionLost) { |
|
|
String workingDirectory = getWorkingDirectory(n); |
|
|
final String fileName = workingDirectory + "/slave.jar"; |
|
|
Future<?> tidyUp = Computer.threadPoolForRemoting.submit(new Runnable() { |
|
|
public void run() { |
|
|
// this would fail if the connection is already lost, so we want to check that. |
|
|
// TODO: Connection class should expose whether it is still connected or not. |
|
|
|
|
|
SFTPv3Client sftpClient = null; |
|
|
try { |
|
|
sftpClient = new SFTPv3Client(connection); |
|
|
sftpClient.rm(fileName); |
|
|
} catch (Exception e) { |
|
|
if (sftpClient == null) {// system without SFTP |
|
|
try { |
|
|
connection.exec("rm " + fileName, listener.getLogger()); |
|
|
} catch (Error error) { |
|
|
throw error; |
|
|
} catch (Throwable x) { |
|
|
x.printStackTrace(listener.error(Messages.SSHLauncher_ErrorDeletingFile(getTimestamp()))); |
|
|
// We ignore other Exception types |
|
|
} |
|
|
} else { |
|
|
e.printStackTrace(listener.error(Messages.SSHLauncher_ErrorDeletingFile(getTimestamp()))); |
|
|
} |
|
|
} finally { |
|
|
if (sftpClient != null) { |
|
|
sftpClient.close(); |
|
|
} |
|
|
} |
|
|
}); |
|
|
try { |
|
|
// the delete is best effort only and if it takes longer than 60 seconds - or the launch |
|
|
// timeout (if specified) - then we should just give up and leave the file there. |
|
|
tidyUp.get(launchTimeoutSeconds == null ? 60 : launchTimeoutSeconds, TimeUnit.SECONDS); |
|
|
} catch (InterruptedException e) { |
|
|
e.printStackTrace(listener.error(Messages.SSHLauncher_ErrorDeletingFile(getTimestamp()))); |
|
|
// we should either re-apply our interrupt flag or propagate... we don't want to propagate, so... |
|
|
Thread.currentThread().interrupt(); |
|
|
} catch (ExecutionException e) { |
|
|
e.printStackTrace(listener.error(Messages.SSHLauncher_ErrorDeletingFile(getTimestamp()))); |
|
|
} catch (TimeoutException e) { |
|
|
e.printStackTrace(listener.error(Messages.SSHLauncher_ErrorDeletingFile(getTimestamp()))); |
|
|
} finally { |
|
|
if (!tidyUp.isDone()) { |
|
|
tidyUp.cancel(true); |
|
|
} |
|
|
} |
|
|
}); |
|
|
try { |
|
|
// the delete is best effort only and if it takes longer than 60 seconds - or the launch |
|
|
// timeout (if specified) - then we should just give up and leave the file there. |
|
|
tidyUp.get(launchTimeoutSeconds == null ? 60 : launchTimeoutSeconds, TimeUnit.SECONDS); |
|
|
} catch (InterruptedException e) { |
|
|
e.printStackTrace(listener.error(Messages.SSHLauncher_ErrorDeletingFile(getTimestamp()))); |
|
|
// we should either re-apply our interrupt flag or propagate... we don't want to propagate, so... |
|
|
Thread.currentThread().interrupt(); |
|
|
} catch (ExecutionException e) { |
|
|
e.printStackTrace(listener.error(Messages.SSHLauncher_ErrorDeletingFile(getTimestamp()))); |
|
|
} catch (TimeoutException e) { |
|
|
e.printStackTrace(listener.error(Messages.SSHLauncher_ErrorDeletingFile(getTimestamp()))); |
|
|
} finally { |
|
|
if (!tidyUp.isDone()) { |
|
|
tidyUp.cancel(true); |
|
|
} |
|
|
} |
|
|
|
|
|
PluginImpl.unregister(connection); |
|
|
cleanupConnection(listener); |
|
|
} |
|
|
|
|
|
PluginImpl.unregister(connection); |
|
|
cleanupConnection(listener); |
|
|
} |
|
|
} |
|
|
|
|
|