SSH: Fix incorrect timeout failures on disconnects. #1479
Closed
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
libcurl is leaking memory when using sftp and a timeout. This was first reported on the mailing list.
The memory leak reported on the mailing list is a symptom of a larger problem - SSH sessions are not freed when a timeout is used. I suspect this problem is also present on other platforms, but may not manifest itself as a memory leak on all platforms.
I used the Visual Studio memory analysis tools to find that libssh2 is leaking some WinCNG structs for each connection. This is because libcurl is never calling the
libssh2_session_free
function when a timeout is set. Without a timeout, the function is called and things get cleaned up correctly.In a disconnect situation, the
close_all_connections
function replaces the easy handle associated with a connection with a 'closure handle'. This will reset all progress values associated with the connection to zero values. As a result, calculations using these values will return incorrect values.The
close_all_connections
function eventually calls into thesftp_disconnect
function, which runs thessh_block_statemach
function. In this function, if a timeout is set, the "time left" value will always be negative, because the start time has been reset to zero. This means that if a timeout is set, disconnections always fail with a timeout error, rather than finish successfully. Since the easy handle has been replaced with the closure handle, this timeout error will not be reported, regardless of the verbose setting used on the original easy handle.