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

HubConnection.Stop takes 30 seconds on Silverlight client #3102

Closed
yowl opened this Issue Jun 28, 2014 · 9 comments

Comments

Projects
None yet
3 participants
@yowl

yowl commented Jun 28, 2014

I attempt to close the SignalR connection before the users logs out of my silverlight client using this code and it takes 30 seconds to do so. I saw #2191 and maybe the fix for the .net client is not applied to the SIlverlight client?

Stop code which takes 30 seconds - this is not called from within an On method..

    void StopChat()
    {
        if (hubConn != null)
        {
            hubConn.Stop();
        }
    }
@DamianEdwards

This comment has been minimized.

Member

DamianEdwards commented Jul 2, 2014

Thanks, we'll take a look. If you can share any more information that may help us to reproduce the issue please do so.

@moozzyk

This comment has been minimized.

Contributor

moozzyk commented Jul 25, 2014

Even though we send Abort request it is actually never sent by the HttpClient when using the portable HttpClient library. The 30 seconds is the default timeout we wait for the response to the Abort request. Until I find out why the underlying HttpClient never sends the Abort request you can use the Stop(TimeSpan) overload and provide a smaller timeout.

@moozzyk moozzyk added 2 - Blocked and removed 1 - Ready labels Jul 25, 2014

@moozzyk

This comment has been minimized.

Contributor

moozzyk commented Jul 29, 2014

It looks that even though the SignalR client invokes HttpClient.SendAsync() the request is actually never sent to the server. I tracked it down to the BeginInvokeImpl method which calls NativeHost.Current.RuntimeHost.RaiseAsyncCallback (see the stack trace below) but the callback (which in this case is the InternalBeginGetResponse) is never invoked. Since from what I could see the InternalBeginGetResponse is responsible for sending the request the request is never sent and the InvokeImpl method is blocked infinitely waiting for the callback to complete.

System.Windows.RuntimeHost.dll!System.Windows.RuntimeHost.ManagedRuntimeHost.RaiseAsyncCallback(System.IntPtr pDelegate, bool useFastPath) Line 191 C# System.Windows.dll!System.Windows.Threading.Dispatcher.BeginInvokeImpl(System.Windows.Threading.DispatcherPriority priority, bool useFastPath, System.Delegate d, object[] args) Line 105 + 0x30 bytes C# System.Windows.dll!System.Windows.Threading.Dispatcher.InvokeImpl(System.Windows.Threading.DispatcherPriority priority, bool useFastPath, System.Delegate d, object[] args) Line 174 + 0x3d bytes C# System.Windows.dll!System.Net.Browser.AsyncHelper.BeginOnUI(System.Net.Browser.BeginMethod beginMethod, System.AsyncCallback callback, object state) Line 142 + 0x4e bytes C# System.Windows.dll!System.Net.Browser.BrowserHttpWebRequest.BeginGetResponse(System.AsyncCallback callback, object state) Line 342 + 0x27 bytes C# System.Net.Http!System.Net.Http.HttpWebRequest.BeginGetResponse(System.AsyncCallback callback, object state) Line 138 + 0x22 bytes C# System.Net.Http!System.Net.Http.HttpClientHandler.StartGettingResponse(System.Net.Http.HttpClientHandler.RequestState state) Line 910 + 0x2b bytes C# System.Net.Http!System.Net.Http.HttpClientHandler.GetRequestStreamCallback.AnonymousMethod__8(System.Threading.Tasks.Task task) Line 883 + 0x15 bytes C# mscorlib.dll!System.Threading.Tasks.ContinuationTaskFromTask.InnerInvoke() Line 58 + 0xc bytes C# mscorlib.dll!System.Threading.Tasks.Task.Execute() Line 2437 + 0xb bytes C# mscorlib.dll!System.Threading.Tasks.Task.ExecutionContextCallback(object obj) Line 2792 + 0x9 bytes C# mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) Line 417 + 0xd bytes C# mscorlib.dll!System.Threading.Tasks.Task.ExecuteWithThreadLocal(ref System.Threading.Tasks.Task currentTaskSlot) Line 2763 C# mscorlib.dll!System.Threading.Tasks.Task.ExecuteEntry(bool bPreventDoubleExecution) Line 2695 + 0x1b bytes C# mscorlib.dll!System.Threading.Tasks.ThreadPoolTaskScheduler.TryExecuteTaskInline(System.Threading.Tasks.Task task, bool taskWasPreviouslyQueued) Line 104 + 0xb bytes C# mscorlib.dll!System.Threading.Tasks.TaskScheduler.TryRunInline(System.Threading.Tasks.Task task, bool taskWasPreviouslyQueued) Line 217 + 0x12 bytes C# mscorlib.dll!System.Threading.Tasks.TaskContinuation.InlineIfPossibleOrElseQueue(System.Threading.Tasks.Task task, bool needsProtection) Line 258 + 0xe bytes C# mscorlib.dll!System.Threading.Tasks.StandardTaskContinuation.Run(System.Threading.Tasks.Task completedTask, bool bCanInlineContinuationTask) Line 323 + 0x53 bytes C# mscorlib.dll!System.Threading.Tasks.Task.ContinueWithCore(System.Threading.Tasks.Task continuationTask, System.Threading.Tasks.TaskScheduler scheduler, System.Threading.CancellationToken cancellationToken, System.Threading.Tasks.TaskContinuationOptions options) Line 4585 + 0x12 bytes C# mscorlib.dll!System.Threading.Tasks.Task.ContinueWith(System.Action<System.Threading.Tasks.Task> continuationAction, System.Threading.Tasks.TaskScheduler scheduler, System.Threading.CancellationToken cancellationToken, System.Threading.Tasks.TaskContinuationOptions continuationOptions, ref System.Threading.StackCrawlMark stackMark) Line 3834 C# mscorlib.dll!System.Threading.Tasks.Task.ContinueWith(System.Action<System.Threading.Tasks.Task> continuationAction, System.Threading.CancellationToken cancellationToken, System.Threading.Tasks.TaskContinuationOptions continuationOptions, System.Threading.Tasks.TaskScheduler scheduler) Line 3799 + 0x1b bytes C# System.Net.Http!System.Net.Http.HttpUtilities.ContinueWithStandard(System.Threading.Tasks.Task task, System.Action<System.Threading.Tasks.Task> continuation) Line 49 + 0x4b bytes C# System.Net.Http!System.Net.Http.HttpClientHandler.GetRequestStreamCallback(System.IAsyncResult ar) Line 866 + 0x7d bytes C# System.Windows.dll!System.Net.Browser.BrowserHttpWebRequest.InvokeGetRequestStreamCallback.AnonymousMethod__12(object state2) Line 786 + 0x11 bytes C# mscorlib.dll!System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(object state) Line 1253 + 0xb bytes C# mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) Line 417 + 0xd bytes C# mscorlib.dll!System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem() Line 1230 + 0x22 bytes C# mscorlib.dll!System.Threading.ThreadPoolWorkQueue.Dispatch() Line 807 C# mscorlib.dll!System.Threading._ThreadPoolWaitCallback.PerformWaitCallback() Line 1145 + 0x5 bytes C#

@moozzyk

This comment has been minimized.

Contributor

moozzyk commented Jul 29, 2014

This is because of a deadlock. We block the thread waiting for the response to the abort request to the server. If the thread we are blocking happens to be the UI thread it will cause a dead lock since Silverlight wants to send the request on the UI thread.

@moozzyk

This comment has been minimized.

Contributor

moozzyk commented Jul 29, 2014

@yowl - one way to work around this issue is to invoke .Stop on a non-UI thread - e.g.: await Task.Factory.StartNew(() => hubConnection.Stop()); another workaround would be to set the Stop timeout to 0 like this: hubConnection.Stop(new TimeSpan(0, 0, 0, 0)); - note that in this case the abort request will never be sent to the server.

@moozzyk moozzyk closed this Jul 29, 2014

@moozzyk moozzyk reopened this Jul 29, 2014

@moozzyk

This comment has been minimized.

Contributor

moozzyk commented Jul 29, 2014

Fixing #3067 will "fix" this issue.

moozzyk added a commit that referenced this issue Jul 31, 2014

TransportAbortHandlerIsMovingOn - removing transport abort handler
(We wish him luck in /dev/null)

Fixes workitems #3067 and #3102

moozzyk added a commit that referenced this issue Jul 31, 2014

TransportAbortHandlerIsMovingOn - removing transport abort handler
(We wish him luck in /dev/null)

Fixes workitems #3067 and #3102

moozzyk added a commit that referenced this issue Aug 4, 2014

TransportAbortHandlerIsMovingOn - removing transport abort handler
(We wish him luck in /dev/null)

Fixes workitems #3067 and #3102
@moozzyk

This comment has been minimized.

Contributor

moozzyk commented Aug 4, 2014

"Fixed" in 7358f1d - we no longer block to receive a response to abort request.

@moozzyk moozzyk added v3 and removed 3 - Working labels Aug 7, 2014

@moozzyk

This comment has been minimized.

Contributor

moozzyk commented Aug 7, 2014

We had to revert the change since it introduced a couple of issues and races we were able to identify and possibly some we have not hit. It became apparent that the change is too risky. We will need to re-think the transport-connection interaction to fix this correctly and/or make the Stop call async.

@DamianEdwards

This comment has been minimized.

Member

DamianEdwards commented Sep 16, 2014

We'll look at this for v3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment