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

The semaphore has been disposed. #102

Open
alexandrius007 opened this issue Apr 20, 2020 · 3 comments
Open

The semaphore has been disposed. #102

alexandrius007 opened this issue Apr 20, 2020 · 3 comments

Comments

@alexandrius007
Copy link

I get error

The semaphore has been disposed.

Could you help to understend the reason of the error?
After error Program has critical error.

<Exception>
<ExceptionType>System.ObjectDisposedException, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType>
<Message>The semaphore has been disposed.</Message>
<StackTrace>
at System.Threading.SemaphoreSlim.CheckDispose()
at System.Threading.SemaphoreSlim.Release(Int32 releaseCount)
at FubarDev.FtpServer.Networking.PausableFtpService.&lt;&gt;c__DisplayClass18_0.&lt;StartAsync&gt;b__0(FtpServiceStatus status)
at System.Progress`1.InvokeHandlers(Object state)
at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
at System.Threading.ThreadPoolWorkQueue.Dispatch()
at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()
</StackTrace>
<ExceptionString>System.ObjectDisposedException: The semaphore has been disposed.
   at System.Threading.SemaphoreSlim.CheckDispose()
   at System.Threading.SemaphoreSlim.Release(Int32 releaseCount)
   at FubarDev.FtpServer.Networking.PausableFtpService.&lt;&gt;c__DisplayClass18_0.&lt;StartAsync&gt;b__0(FtpServiceStatus status)
   at System.Progress`1.InvokeHandlers(Object state)
   at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
   at System.Threading.ThreadPoolWorkQueue.Dispatch()
   at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()</ExceptionString>
</Exception>

@dmansurov83
Copy link

We have the same case when the connection was closed immediately after opening. I guess the Progress implementation is to blame here:

using (var semaphore = new SemaphoreSlim(0, 1))
{
    _jobPaused = new CancellationTokenSource();
    _task = RunAsync(
        new Progress<FtpServiceStatus>(
            status =>
            {
                Status = status;

                if (status == FtpServiceStatus.Running)
                {
                    // ReSharper disable once AccessToDisposedClosure
                    semaphore.Release();
                }
            }));

    await semaphore.WaitAsync(cancellationToken);
}

The Progress uses SyncronizationContext.Post to pass progress data and, theoretically, can be invoked after the semaphore will be disposed.

@heppth
Copy link

heppth commented Jun 15, 2021

I have encountered the same issue. In my case, the problem occurred in conjunction with SslStreamConnectionAdapter (explicit encryption).

This exception encountered before: Status must be Running, Stopped, or Paused, but was ReadyToRun.

System.InvalidOperationException:
   at FubarDev.FtpServer.Networking.PausableFtpService+<StopAsync>d__19.MoveNext (FubarDev.FtpServer, Version=3.1.1.0, Culture=neutral, PublicKeyToken=null)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at FubarDev.FtpServer.ConnectionHandlers.SslStreamConnectionAdapter+<StopAsync>d__12.MoveNext (FubarDev.FtpServer, Version=3.1.1.0, Culture=neutral, PublicKeyToken=null)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at FubarDev.FtpServer.FtpConnection+<StopAsync>d__61.MoveNext (FubarDev.FtpServer, Version=3.1.1.0, Culture=neutral, PublicKeyToken=null)

Immediately after that the same exception occured: The semaphore has been disposed.

System.ObjectDisposedException:
   at System.Threading.SemaphoreSlim.CheckDispose (System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at System.Threading.SemaphoreSlim.Release (System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at FubarDev.FtpServer.Networking.PausableFtpService+<>c__DisplayClass18_0.<StartAsync>b__0 (FubarDev.FtpServer, Version=3.1.1.0, Culture=neutral, PublicKeyToken=null)
   at System.Progress`1.InvokeHandlers (System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
   at System.Threading.ThreadPoolWorkQueue.Dispatch (System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)

@alexandrius007
Copy link
Author

This class extension helps to solve this problem:

 internal class SemaphoreSlimExt : SemaphoreSlim
    {
             public SemaphoreSlimExt(int initialCount)
            : base(initialCount)
        {
        }
        public SemaphoreSlimExt(int initialCount, int maxCount)
            : base(initialCount, maxCount)
        {
        }

        public bool IsDisposed { get; internal set; }

        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);
            IsDisposed = true;
        }
    }

and after

  using (var semaphore = new SemaphoreSlimExt(0, 1))
                {
                    _jobPaused = new CancellationTokenSource();
                    _task = RunAsync(
                        new Progress<FtpServiceStatus>(
                            status =>
                            {
                                Status = status;

                                if (status == FtpServiceStatus.Running && **!semaphore.IsDisposed**)
                                {
                                    // ReSharper disable once AccessToDisposedClosure
                                    semaphore?.Release();
                                }
                            }));

                    var res = semaphore.WaitAsync(cancellationToken);
                    res.Wait();
                }

alexandrius007 pushed a commit to alexandrius007/FtpServer that referenced this issue Oct 6, 2022
+ MemberValidationStatus : TooManyUsers
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

3 participants