Ticket #66 (closed defect)

Opened 9 years ago

Last modified 8 years ago

SSH disconnect detection

Reported by: gmiller1018 Owned by:
Priority: normal Milestone:
Component: misc Version:
Keywords: Cc: gmiller1018, bagder
Blocked By: Blocks:

Description

When using libssh2_poll with a INT max timeout and a socket disconnects there does not seem to be any response. I had expected the libssh2_poll to return with the appropriate status indication.

Status passed in as:
[code]

cur_fd->fd.channel = sess_flags[I].channel; channel

cur_fd->type = LIBSSH2_POLLFD_CHANNEL;
cur_fd->events = LIBSSH2_POLLFD_POLLIN |

LIBSSH2_POLLFD_POLLERR |
LIBSSH2_POLLFD_POLLHUP |
LIBSSH2_POLLFD_POLLNVAL |
LIBSSH2_POLLFD_SESSION_CLOSED |
LIBSSH2_POLLFD_CHANNEL_CLOSED;

twait = INT_MAX; wait forever for input or disconn.
Log_debug("Waiting in libssh2_poll");
nfound = libssh2_poll (ssh_fds, count, twait);
Log_debug("libssh2_poll returned");

code

there is only one socket open at the time and count is
set to 1 (in a select I would use 2). I am unsure if there is some behavior or other issue I need to consider to make this work. In past version of the library this worked but I had customized the code because of blocking behavior. This is pure latest release running on Fedora 7 using the RPM's. The connect and read and write appears to work correctly in general use but if the remote system server crashes the disconnect is not signaled so I never try to re-connect.

The socket have been set to non blocking by:
[code]

libssh2_channel_set_blocking(sess_flags[I].channel,

0); make nonblocking

code

Change History

comment:1 Changed 9 years ago by gmiller1018

After further investigation there are a number of problems.
1.) If HAVE_POLL and HAVE_SELECT are both true then select will never be used. I put a #undef HAVE_POLL to address this.
2.) To have the select return when the socket disconnect the select calls need to have select(maxfds +1 ...)
3.) The loop reading data till complete does not set anything that indicates the socket has closed because of the way it checks

for a WOULD_BLOCK error (using the Windows terminology, I am using Linux)

4.) The code in the libssh2_poll for the select would not set the correct status to indicate the socket was closed.

comment:2 Changed 9 years ago by anonymous

Logged In: NO

To work around the issue I modified the code in session.c at line 1544 to be:
[code libssh2 session.c]

case LIBSSH2_POLLFD_CHANNEL:

if (FD_ISSET(fds[i].fd.channel->session->socket_fd, &rfds)) {

int rc;

fds[i].revents |= LIBSSH2_POLLFD_POLLIN; force data flag ...(gwm)
/* Spin session until no data available */
while ((rc = libssh2_packet_read(fds[i].fd.channel->session)) > 0);
modified to get return code at exit (gwm)
check for socket closed ...
if ( rc == PACKET_FAIL )
new (gwm)

fds[i].revents |= new (gwm)

LIBSSH2_POLLFD_CHANNEL_CLOSED | new (gwm)
LIBSSH2_POLLFD_SESSION_CLOSED;
new (gwm) .. the first change might be all thats needed

active_fds++;
}
break;

[/code libssh2 (session.c)

In my code I use:
[my code]
if (ssh_fds[j].revents | (LIBSSH2_POLLFD_CHANNEL_CLOSED |

LIBSSH2_POLLFD_SESSION_CLOSED)) {

length = 0; signal no data so we will close socket
Log_debug("SSH lost connection");

}
else {

length = libssh2_channel_read (sess_flags[I].channel, channel

iptr[I], buffer
length);
max space in buffer

Log_debug("Got %d SSH byte(s)", length);

}

mycode

The read if we ignore the close flags returns -37 ( libssh2's EAGAIN)

Of course this change is after I did the #undef HAVE_POLL so select() would be
used and not poll().

At this point all appears to be working and the disconnect is being returned to
my code so it can close the sockets and retry the connection and re-port forward.

Of course my solution might not be an acceptable way of doing what you intended
so please do not react negatively.

I think the build environment needs to "undef" HAVE_POLL if select is available
or split the functionality so one has precedence over the other. The read
should set the events data to should a read has been done and the socket close
flags need to be indicated as well (or one or the other, if we close the heck with
the data.

I chose the PACKET_ERROR return code since that will be returned if the recv in
libssh2_packet_read gets 0 bytes with no error (graceful socket exit).

Please let me know if there is a more general way to solve these issues so I can
get them fixed in some upcoming release. I have been fixing the select() / poll()
issue for a while.

comment:3 Changed 9 years ago by gmiller1018

All comments were made by me ... I fogot to log in prior to adding them ... sorry

comment:4 Changed 8 years ago by bagder

Can you please post your suggested changes as a "regular" diff -u output/patch ?

comment:5 Changed 8 years ago by bagder

libssh2_poll() is now considered deprecated so this bug will not be fixed. You should simply not use this function anymore...

Note: See TracTickets for help on using tickets.