From 33dddd2f8ac3bc811719e6422e9bec6458f91de3 Mon Sep 17 00:00:00 2001 From: Miguel de Icaza Date: Wed, 26 Apr 2023 14:51:19 -0400 Subject: [PATCH] If SFTP fails to initialize, do not busy loop waiting for IO to happen (#720) Currently SFTP's init will busy loop waiting for the channel to close, even if the underlying transport returns EAGAIN. While this works for sockets, it might not work out if you have a different transport that needs to do some additional processing on the side. Integration-patches-by: Viktor Szakats --- src/libssh2_priv.h | 1 + src/sftp.c | 25 +++++++++++++++++-------- src/transport.c | 3 ++- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/libssh2_priv.h b/src/libssh2_priv.h index 49b2095d..6cbb2532 100644 --- a/src/libssh2_priv.h +++ b/src/libssh2_priv.h @@ -262,6 +262,7 @@ typedef enum libssh2_NB_state_jump3, libssh2_NB_state_jump4, libssh2_NB_state_jump5, + libssh2_NB_state_error_closing, libssh2_NB_state_end, libssh2_NB_state_jumpauthagent } libssh2_nonblocking_states; diff --git a/src/sftp.c b/src/sftp.c index d6c39e1e..6f577378 100644 --- a/src/sftp.c +++ b/src/sftp.c @@ -894,6 +894,22 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session) } } + if(session->sftpInit_state == libssh2_NB_state_error_closing) { + rc = _libssh2_channel_free(session->sftpInit_channel); + if(rc == LIBSSH2_ERROR_EAGAIN) { + _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, + "Would block closing channel"); + return NULL; + } + session->sftpInit_channel = NULL; + if(session->sftpInit_sftp) { + LIBSSH2_FREE(session, session->sftpInit_sftp); + session->sftpInit_sftp = NULL; + } + session->sftpInit_state = libssh2_NB_state_idle; + return NULL; + } + rc = sftp_packet_require(sftp_handle, SSH_FXP_VERSION, 0, &data, &data_len, 5); if(rc == LIBSSH2_ERROR_EAGAIN) { @@ -970,14 +986,7 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session) return sftp_handle; sftp_init_error: - while(_libssh2_channel_free(session->sftpInit_channel) == - LIBSSH2_ERROR_EAGAIN); - session->sftpInit_channel = NULL; - if(session->sftpInit_sftp) { - LIBSSH2_FREE(session, session->sftpInit_sftp); - session->sftpInit_sftp = NULL; - } - session->sftpInit_state = libssh2_NB_state_idle; + session->sftpInit_state = libssh2_NB_state_error_closing; return NULL; } diff --git a/src/transport.c b/src/transport.c index 8646608b..bce6413d 100644 --- a/src/transport.c +++ b/src/transport.c @@ -777,7 +777,8 @@ send_existing(LIBSSH2_SESSION *session, const unsigned char *data, we don't add this one up until the previous one has been sent. To make the caller really notice his/hers flaw, we return error for this case */ - return LIBSSH2_ERROR_BAD_USE; + _libssh2_debug((session, LIBSSH2_TRACE_SOCKET, + "Address is different, but will resume nonetheless")); } *ret = 1; /* set to make our parent return */