Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exception in ChannelSession ReleaseSemaphore #400

Closed
fabricedupre opened this issue Mar 8, 2018 · 3 comments
Closed

Exception in ChannelSession ReleaseSemaphore #400

fabricedupre opened this issue Mar 8, 2018 · 3 comments
Milestone

Comments

@fabricedupre
Copy link

Hello,

I am using latest stable release 2016.1.0 on Windows 10 with Visual Studio 2017 within a desktop application.

ReleaseSemaphore sometimes throws a SystemNullReference exception. To circumvent that issue I had to modify the function to:

    private void ReleaseSemaphore()
    {
        if (Interlocked.CompareExchange(ref _sessionSemaphoreObtained, 0, 1) == 1)
        {
                SemaphoreLight sem = SessionSemaphore;

                if (sem != null)
                    sem.Release();
                else
                    System.Diagnostics.Trace.WriteLine("*** SessionSemaphore NULL");
        }
    }

Digging a little bit, I found that in fact the issue came from Channel SessionSemaphore property. I also had to change it a little bit as below:

    protected SemaphoreLight SessionSemaphore
    {
        get
        {
                ISession s = _session;

                if (s != null)
                    return s.SessionSemaphore;
            
                System.Diagnostics.Trace.WriteLine("*** session NULL");
                return null;
        }
    }

Running my app with those changes, I sometimes get the below trace output, but no more exception:
*** session NULL
*** SessionSemaphore NULL

@marcellemke
Copy link

marcellemke commented Oct 13, 2020

I occasionally had the same when I was calling the following code a lot of times (compiled SSH.Net in Debug mode as well!):

using (var cmd = sshclient.CreateCommand(cmdStr))
{
	var result = cmd.Execute();
}

As I figured out, ChannelSession.Close() has been called a second time when the exception occured.

In Session.OnChannelCloseReceived (on message handling thread), different handlers will be processed.
When exception happens, SshCommand.Channel_Closed() is being processed before Channel.OnClose(). So in my code cmd.Execute() finishes on main thread and cmd.Dispose() is being called. After Channel.Dispose() has been called in SshCommand.Dispose() (setting _session in ChannelSession to null), Channel.OnClose() is being started on the message handling thread => ReleaseSemaphore() will fail (NullReferenceException in Semaphore.get)!

(In the screenshot I made, the main thread not only disposed the SshCommand where the exception occured, but it already created next SshCommand)

I think the fix made by fabricedupre is fine: Channel.Close()/ChannelSession.Close() are being handled at least one time (on first call) correctly.
Another solution might be to insert one of the following checks in first line of Close() methods - that won't provide full thread safety like fabricedupre' does, but those handlers in Session.OnChannelCloseReceived should all be handled sequentially on the message handling thread anyway:

if (!this.IsOpen) return;
if (this.IsDisposed) return;

renci_except

@Rob-Hague
Copy link
Collaborator

Closed by #1071. Thanks @marcellemke

@WojciechNagorski

@WojciechNagorski WojciechNagorski added this to the 2023.0.0 milestone Sep 28, 2023
@WojciechNagorski
Copy link
Collaborator

Version 2023.0.0 has been published https://www.nuget.org/packages/SSH.NET/2023.0.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants