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