-
Notifications
You must be signed in to change notification settings - Fork 2.3k
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
InvalidOperationException when set HubProxy Item property during executing HubProxy Invoke method in SignalR .Net client #3497
Comments
Why do you want to set the state and call Invoke in parallel? The state is sent to the server when you call Invoke so these calls should be serialized otherwise there is a race condition and the state data you set may not to be sent to the server. Also the indexer is a synchronous method so setting it "in parallel with Invoke" means that either you create your own threads in which case you should ensure the right ordering of calls or you first invoke the Invoke method without awaiting and then you set the state in which case you probably should reorder the calls. |
I found this issue during I wrote a stress test tool for SignalR WebServer. Several worker threads run in parallel and these threads share the same HubProxy instance. |
I think this is the same issue as the one i raised here: #3631 I agree with tanaka, there is inconsistent locking around _state. Either its thread safe or its not, the existence of locking at all suggests to me that it should be thread safe. |
Almost a year old an no comment :-( |
The OP mentions that parallel calls to the indexer and Invoke expose this bug. However, it seems that two parallel calls to Invoke will also expose the issue, as the callback sets state via that same indexer. https://github.com/SignalR/SignalR/blob/master/src/Microsoft.AspNet.SignalR.Client/Hubs/HubProxy.cs#L128 |
Why do you need to call hub methods in parallel? Why not work around the issue but serializing calls to the hub proxy? |
Actually I can work around. However, as goldenc and daniel-smith said, there is inconsistent locking. |
Agreed, I'm just making sure this isn't blocking you |
The reason we call things in parallel is simply because we await multiple, potentially long-ish running, request/response results in parallel. Even if we did serialise calls to Invoke, I would have thought we have no control over the callback thread - so I'm not sure this would solve the issue. I.e. we couldn't serialise the callback work, which can still update state while another serialized call to Invoke is happening. |
This issue has been closed as part of issue clean-up as described in https://blogs.msdn.microsoft.com/webdev/2018/09/17/the-future-of-asp-net-signalr/. If you're still encountering this problem, please feel free to re-open and comment to let us know! We're still interested in hearing from you, the backlog just got a little big and we had to do a bulk clean up to get back on top of things. Thanks for your continued feedback! |
Functional impact
I found InvalidOperationException is thrown with HubProxy _state lock condition.
I use latest version of Microsoft.AspNet.SignalR.Client (2.2.0).
Repro steps
Expected result
Invoke method runs with successfully.
Actual result
Then Invoke method may thorw InvalidOperationException with "Collection was modified; enumeration operation may not execute.".
Further technical details
HubProxy Item Property (indexer) gets or sets the "_state" field with lock statement.
https://github.com/SignalR/SignalR/blob/master/src/Microsoft.AspNet.SignalR.Client/Hubs/HubProxy.cs#L27-L45
The "_state" is IDictionary<string, JToken> and this filed passes to "hubData" local variable in Invoke method.
https://github.com/SignalR/SignalR/blob/master/src/Microsoft.AspNet.SignalR.Client/Hubs/HubProxy.cs#L159-L172
So InvalidOperationException is thrown if Item property is set during executing Invoke method.
This is because dictionary in "hubData" variable is enumerated in Json.Net library.
https://github.com/JamesNK/Newtonsoft.Json/blob/master/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs#L926
Just an idea, this code will solve this issue.
The text was updated successfully, but these errors were encountered: