throw new IllegalStateException("Already connected");
final TaskListener taskListener = new StreamTaskListener(launchLog);
PrintStream log = taskListener.getLogger();
Channel channel = new Channel(nodeName,threadPoolForRemoting, Channel.Mode.NEGOTIATE,
in,out, launchLog);
channel.addListener(new Channel.Listener() {
@Override
public void onClosed(Channel c, IOException cause) {
SlaveComputer.this.channel = null;
// Orderly shutdown will have null exception
if (cause!=null) {
offlineCause = new ChannelTermination(cause);
cause.printStackTrace(taskListener.error("Connection terminated"));
} else {
taskListener.getLogger().println("Connection terminated");
}
launcher.afterDisconnect(SlaveComputer.this, taskListener);
}
});
if(listener!=null)
channel.addListener(listener);
String slaveVersion = channel.call(new SlaveVersion());
log.println("Slave.jar version: " + slaveVersion);
boolean _isUnix = channel.call(new DetectOS());
log.println(_isUnix? hudson.model.Messages.Slave_UnixSlave():hudson.model.Messages.Slave_WindowsSlave());
String defaultCharsetName = channel.call(new DetectDefaultCharset());
String remoteFs = getNode().getRemoteFS();
if(_isUnix && !remoteFs.contains("/") && remoteFs.contains("\\"))
log.println("WARNING: "+remoteFs+" looks suspiciously like Windows path. Maybe you meant "+remoteFs.replace('\\','/')+"?");
FilePath root = new FilePath(channel,getNode().getRemoteFS());
channel.call(new SlaveInitializer());
channel.call(new WindowsSlaveInstaller(remoteFs));
for (ComputerListener cl : ComputerListener.all())
cl.preOnline(this,channel,root,taskListener);
offlineCause = null;
// update the data structure atomically to prevent others from seeing a channel that's not properly initialized yet
synchronized(channelLock) {
if(this.channel!=null) {
// check again. we used to have this entire method in a big sycnhronization block,
// but Channel constructor blocks for an external process to do the connection
// if CommandLauncher is used, and that cannot be interrupted because it blocks at InputStream.
// so if the process hangs, it hangs the thread in a lock, and since Hudson will try to relaunch,
// we'll end up queuing the lot of threads in a pseudo deadlock.
// This implementation prevents that by avoiding a lock. HUDSON-1705 is likely a manifestation of this.
channel.close();
throw new IllegalStateException("Already connected");
}
isUnix = _isUnix;
numRetryAttempt = 0;
this.channel = channel;