Search in sources :

Example 1 with ChannelTermination

use of hudson.slaves.OfflineCause.ChannelTermination in project hudson-2.x by hudson.

the class SlaveComputer method setChannel.

/**
     * Creates a {@link Channel} from the given stream and sets that to this slave.
     *
     * @param in
     *      Stream connected to the remote "slave.jar". It's the caller's responsibility to do
     *      buffering on this stream, if that's necessary.
     * @param out
     *      Stream connected to the remote peer. It's the caller's responsibility to do
     *      buffering on this stream, if that's necessary.
     * @param launchLog
     *      If non-null, receive the portion of data in <tt>is</tt> before
     *      the data goes into the "binary mode". This is useful
     *      when the established communication channel might include some data that might
     *      be useful for debugging/trouble-shooting.
     * @param listener
     *      Gets a notification when the channel closes, to perform clean up. Can be null.
     *      By the time this method is called, the cause of the termination is reported to the user,
     *      so the implementation of the listener doesn't need to do that again.
     */
public void setChannel(InputStream in, OutputStream out, OutputStream launchLog, Channel.Listener listener) throws IOException, InterruptedException {
    if (this.channel != null)
        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;
        defaultCharset = Charset.forName(defaultCharsetName);
    }
    for (ComputerListener cl : ComputerListener.all()) cl.onOnline(this, taskListener);
    log.println("Slave successfully connected and online");
    Hudson.getInstance().getQueue().scheduleMaintenance();
}
Also used : FilePath(hudson.FilePath) PrintStream(java.io.PrintStream) StreamTaskListener(hudson.util.StreamTaskListener) Channel(hudson.remoting.Channel) VirtualChannel(hudson.remoting.VirtualChannel) IOException(java.io.IOException) WindowsSlaveInstaller(hudson.lifecycle.WindowsSlaveInstaller) StreamTaskListener(hudson.util.StreamTaskListener) ChannelTermination(hudson.slaves.OfflineCause.ChannelTermination)

Aggregations

FilePath (hudson.FilePath)1 WindowsSlaveInstaller (hudson.lifecycle.WindowsSlaveInstaller)1 Channel (hudson.remoting.Channel)1 VirtualChannel (hudson.remoting.VirtualChannel)1 ChannelTermination (hudson.slaves.OfflineCause.ChannelTermination)1 StreamTaskListener (hudson.util.StreamTaskListener)1 IOException (java.io.IOException)1 PrintStream (java.io.PrintStream)1