Correct way to free a session _and_ how to do so without blocking or timeout

Evan M etm2131 at columbia.edu
Mon Feb 7 02:10:58 CET 2022


Following up to see if anyone is willing to share their thoughts on any of
these questions. Even a partial answer would be helpful to know whether I
am thinking about this correctly.

Thank you
-Evan

On Tue, Jan 11, 2022 at 10:55 PM Evan M <etm2131 at columbia.edu> wrote:

> Hi all - apologies for the long email.. I want to make sure I'm explaining
> things clearly.
>
> I am working on a wrapper over libssh2 for the Rust programming language.
> Rust has RAII similar to C++ where resources for a struct / object are
> released when the struct is dropped (i.e. goes out of scope). Since
> destructors run in a single shot and should ideally be non-blocking, we
> need a way to release session resources without performing blocking IO (or
> any IO at all). This is especially important when using libssh2 in a
> non-blocking async context.
>
> My question has two parts. First, I want to make sure I understand the
> correct way to completely close a session without leaking any memory. I
> believe there is some complexity involved since libssh2 mixes SSH protocol
> IO with freeing memory in most (maybe all) of the cleanup functions (such
> as libssh2_session_free() and libssh2_channel_free()).
>
> Is this the procedure below the correct way to close a session? For each
> of these steps I'm assuming the functions are retried until they succeed in
> the case of LIBSSH2_ERROR_EAGAIN or LIBSSH2_ERROR_TIMEOUT being returned.
>
> 1. Call the appropriate shutdown / free function for any and all objects
> associated with the session (i.e. libssh2_sftp_shutdown(),
> libssh2_channel_free(), libssh2_channel_forward_cancel(), etc...). These
> functions perform IO in addition to freeing memory.
>
> 2. Call libssh2_session_disconnect() to send the SSH disconnect message
>
> 3. Call libssh2_session_free(); At this point I believe
> libssh2_session_free() should not perform any IO since all channels and
> listeners have already been closed. I read through the code and this seems
> to be the case, but perhaps I missed something.
>
> On this last point, I also didn't see any code preventing libssh2 from
> sending data to the server after it has sent a disconnect message, even
> though the SSH spec states that no further transmissions are permitted. I'm
> therefore assuming that if libssh2_session_disconnect() is called before
> the channel_free or similar, libssh2 will continue sending messages to the
> server in these cleanup functions. It also looks like libssh2_session_free
> will cause IO to close channels if they are still open when it is called.
>
>
> Second, I'd like to understand how to clean up in a non-blocking context
> where we cannot wait for IO to complete, such as in the destructor for a
> struct in our Rust library. Is it alright to call
> shutdown() in a UNIX environment to close the socket without recycling the
> fd and then call the appropriate free/shutdown/cancel functions before
> calling libssh2_session_free()? The thought is that after calling shutdown
> on the socket any IO performed by the libssh2 code will fail, which from my
> understanding will cause libssh2_session_free() to discard the IO error and
> proceed through the routine, freeing the session memory. This allows us to
> avoid EAGAIN and timeouts in the destructor at the cost of closing the
> socket without cleanly ending the SSH session.
>
> Thanks!
>
> - Evan
>
> --
> Evan Mesterhazy
> etm2131 at columbia.edu
>


-- 
Evan Mesterhazy
etm2131 at columbia.edu
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.haxx.se/pipermail/libssh2-devel/attachments/20220206/6c5490e1/attachment.htm>


More information about the libssh2-devel mailing list