a recent mailing list item reported a NullPointerException from  
Channel.connect():
http://sourceforge.net/mailarchive/message.php?msg_name=64efa1ba0905060135n23e14c87rb0ee95eecc385443%40mail.gmail.com

I've seen the same thing on a project I'm currently working on.  We  
have observed it connecting from a CentOS (5.2) and a Fedora 7 machine  
to a RedHat 5.1 x86_64 server, although have not managed to repeat it  
connecting from a Windows machine to the server.  Interestingly it  
happens for with two particular user accounts but not two other  
accounts.  We've also seen the failure on two separate servers (RedHat  
5.0 and RedHat 5.2).

The failure has occurred in a number of different contexts.  In one  
context we have a GUI application with a dialogue that accepts  
username/password and attempts to connect to run a simple command to  
confirm the authentication details provided are correct.  If the  
authentication fails, the same dialogue with the same authentication  
details are provided again.  We see failures here where  
username/password are entered the first time the dialogue is  
displayed, then submitted, authentication fails, resubmit with the  
same details, - this cycle can occur 2 to 4 times before the same  
authentication details result in success.

Here is a sample exception caught:
com.jcraft.jsch.JSchException:
java.lang.NullPointerException
  at com.jcraft.jsch.Channel.connect(Channel.java:206)
  at pac_core.support.SshAccess.runCommand(SshAccess.java:182)
  at
pac_core.job.FileSystemInfoRetrievalJob$FileSystemJobActionCallback.action(FileSystemInfoRetrievalJob.java:78)
  at  
pac_core.job.RemoteCommandJob.runActionCallbackViaSsh(RemoteCommandJob.java:134)
  at pac_core.job.RemoteCommandJob.run(RemoteCommandJob.java:93)
  at  
pac_core.job.FileSystemInfoRetrievalJob.run(FileSystemInfoRetrievalJob.java:46)
  at org.eclipse.core.internal.jobs.Worker.run(Worker.java:55)

The stack for when the original error that occurs within jsch is:
   ChannelExec.start(): line 52
   ChannelExec(Channel).connect(int): line 200
where the following check occurs:
       if(io.in!=null){
Using the eclipse debugger, io is null.

The Channel.io and Channel.close fields are defined but are eventually  
set to null and true respectively by an separate thread:
  ChannelExec(Channel).disconnect()
  Session.run() line 1328
  Thread.run() line 619
Specifically, Channel.java line 538 sets io to null

It seems that at the very least Channel.io should be checked prior to  
use, however there is probably a race condition here requiring some  
form of synchronization between checking io and io.in.

Interestingly, if I invoke:
  channel.connect();
instead of
  channel.connect(30000);
I don't see the failure.  I see if a timeout is set, the "want reply"  
flag is set in the SSH_MSG_CHANNEL_REQUEST request (RequestExec.java  
line 53).  Hunting around the web, I see there is some discussion of  
the way OpenSSH has implemented this aspect of the protocol (e.g.  
http://fixunix.com/ssh/74351-incorrect-protocol-implementation-openssh.html),  
so perhaps that is related.

My client code looks like:
      private Session makeSession(MachineConfig machine, String  
username, String password)
      {
          String host = machine.getHostName();

          Ssh ssh = machine.getRemoteCommandMethod().getSsh();
          if (ssh == null)
          {
              throw new PacException("Machine " + host
                                     + " is not configured for ssh  
remote command execution.");
          }
          Port port = ssh.getPort();
          int portNumber = port == null ? DEFAULT_SSH_PORT : port.getNumber();

          Session session = null;
          try
          {
              initLogging();

              JSch jsch = new JSch();
              session = jsch.getSession(username, host, portNumber);
              session.setPassword(password);
              session.setConfig("StrictHostKeyChecking", "no");
              session.connect(30000);
              return session;
          }
          catch (Exception e)
          {
              if (session != null && session.isConnected())
              {
                  session.disconnect();
              }
              throw new PacException("Failed to create new SSH session.", e);
          }
      }

      public String runCommand(String command)
          throws PacException
      {
          long sshWait = CorePlugin.getDefault().getProperty(SSH_WAIT_PROPERTY,
                                                              
SSH_WAIT_PROPERTY_DEFAULT_MILLIS);

          Channel channel = null;
          ByteArrayOutputStream errStream = new ByteArrayOutputStream();
          try
          {
              if (session == null || !session.isConnected())
              {
                  session = makeSession(machine, username, password);
              }

              channel = session.openChannel("exec");
              channel.setInputStream(null);
              ((ChannelExec)channel).setCommand(command);

              InputStream in=channel.getInputStream();
              ((ChannelExec)channel).setErrStream(errStream);

              // TODO make timeout configurable and confirm how it works
              channel.connect(30000);

              StringBuilder outputBuf = new StringBuilder();
              byte[] tmp=new byte[1024];
              while (true)
              {
                  while (in.available() > 0)
                  {
                      int i = in.read(tmp, 0, 1024);
                      if (i < 0)
                      {
                          break;
                      }
                      outputBuf.append(new String(tmp, 0, i));
                  }
                  if (channel.isClosed())
                  {
                      int exitStatus = channel.getExitStatus();
                      if (exitStatus != 0)
                      {
                          CorePlugin.getLogger().info("SSH remote  
command '" + command
                                                      + "' returned  
exit status " + exitStatus);
                      }
                      break;
                  }

                  try
                  {
                      Thread.sleep(sshWait);
                  }
                  catch (Throwable t)
                  {
                  }
              }

              return outputBuf.toString();
          }
          catch (Exception e)
          {
             ...
          }
          finally
          {
              if (channel != null && channel.isConnected())
              {
                  channel.disconnect();
              }
              ...
          }
      }

I am using jsch version 0.41.

I'm more than happy to run tests, provide debugging info, etc to help
resolve this issue.

Regards,

Daniel

------------------------------------------------------------------------------
The NEW KODAK i700 Series Scanners deliver under ANY circumstances! Your
production scanning environment may not be a perfect world - but thanks to
Kodak, there's a perfect scanner to get the job done! With the NEW KODAK i700
Series Scanner you'll get full speed at 300 dpi even with all image 
processing features enabled. http://p.sf.net/sfu/kodak-com
_______________________________________________
JSch-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/jsch-users

Reply via email to