Skip to content

Commit 4a13d85

Browse files
author
Elad Zelingher
committed
Trying to fix #91 race conditions
and NullReferenceException logs in AsyncWampConnection.
1 parent 3b960f8 commit 4a13d85

File tree

6 files changed

+71
-26
lines changed

6 files changed

+71
-26
lines changed

src/net45/WampSharp/Core/Listener/Connections/AsyncConnection/AsyncWampConnection.cs

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -27,46 +27,64 @@ public void Send(WampMessage<object> message)
2727

2828
protected async Task InnerSend(WampMessage<object> message)
2929
{
30+
const string errorMessage =
31+
"An error occured while attempting to send a message to remote peer.";
32+
3033
if (IsConnected)
3134
{
3235
try
3336
{
3437
Task sendAsync = SendAsync(message);
3538

36-
await sendAsync.ConfigureAwait(false);
39+
if (sendAsync != null)
40+
{
41+
await sendAsync.ConfigureAwait(false);
42+
}
43+
else
44+
{
45+
mLogger.Error(errorMessage + " Got null Task.");
46+
}
3747
}
3848
catch (Exception ex)
3949
{
40-
mLogger.Error("An error occured while attempting to send a message to remote peer.", ex);
50+
mLogger.Error(errorMessage, ex);
4151
}
4252
}
4353
}
4454

4555
#else
4656
protected Task InnerSend(WampMessage<object> message)
4757
{
58+
const string errorMessage =
59+
"An error occured while attempting to send a message to remote peer.";
60+
4861
if (IsConnected)
4962
{
5063
Task sendAsync = SendAsync(message);
51-
52-
Task result = sendAsync.ContinueWith(task =>
53-
{
54-
var ex = task.Exception;
5564

56-
if (ex != null)
65+
if (sendAsync == null)
66+
{
67+
mLogger.Error(errorMessage + " Got null Task.");
68+
}
69+
else
70+
{
71+
Task result = sendAsync.ContinueWith(task =>
5772
{
58-
mLogger.Error("An error occured while attempting to send a message to remote peer.", ex);
59-
}
60-
});
61-
62-
return result;
63-
}
64-
else
65-
{
66-
TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();
67-
tcs.SetResult(null);
68-
return tcs.Task;
73+
var ex = task.Exception;
74+
75+
if (ex != null)
76+
{
77+
mLogger.Error(errorMessage, ex);
78+
}
79+
});
80+
81+
return result;
82+
}
6983
}
84+
85+
TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();
86+
tcs.SetResult(null);
87+
return tcs.Task;
7088
}
7189

7290
#endif

src/net45/WampSharp/Core/Utilities/DictionaryExtensions.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,31 @@
11
using System;
2+
using System.Collections.Concurrent;
23
using System.Collections.Generic;
34

45
namespace WampSharp.Core.Utilities
56
{
67
internal static class DictionaryExtensions
78
{
9+
public static bool TryRemoveExact<TKey, TValue>
10+
(this ConcurrentDictionary<TKey, TValue> dictionary,
11+
TKey key,
12+
TValue value)
13+
{
14+
bool result = false;
15+
TValue dictionaryValue;
16+
17+
if (dictionary.TryGetValue(key, out dictionaryValue))
18+
{
19+
if (object.ReferenceEquals(dictionaryValue, value))
20+
{
21+
TValue removed;
22+
result = dictionary.TryRemove(key, out removed);
23+
}
24+
}
25+
26+
return result;
27+
}
28+
829
public static bool Remove<TKey, TValue>(this IDictionary<TKey, ICollection<TValue>> dictionary,
930
TKey key,
1031
TValue value)

src/net45/WampSharp/Core/Utilities/IdMapperBase.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ public bool TryRemove(TKey id, out T value)
3434
return mIdToValue.TryRemove(id, out value);
3535
}
3636

37+
public bool TryRemoveExact(TKey id, T value)
38+
{
39+
return mIdToValue.TryRemoveExact(id, value);
40+
}
41+
3742
public void Clear()
3843
{
3944
mIdToValue.Clear();

src/net45/WampSharp/WAMP2/V2/PubSub/MatchTopicContainer.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Collections.Concurrent;
33
using System.Collections.Generic;
44
using WampSharp.Core.Serialization;
5+
using WampSharp.Core.Utilities;
56
using WampSharp.V2.Core.Contracts;
67

78
namespace WampSharp.V2.PubSub
@@ -184,15 +185,14 @@ private void OnTopicEmpty(object sender, EventArgs e)
184185
{
185186
lock (mLock)
186187
{
187-
IWampTopic topic = sender as IWampTopic;
188+
WampTopic topic = sender as WampTopic;
188189

189190
if (!topic.HasSubscribers)
190191
{
191192
topic.TopicEmpty -= OnTopicEmpty;
192193
topic.Dispose();
193194

194-
IWampTopic deletedTopic;
195-
TryRemoveTopicByUri(topic.TopicUri, out deletedTopic);
195+
mTopicUriToSubject.TryRemoveExact(topic.TopicUri, topic);
196196
}
197197
}
198198
}

src/net45/WampSharp/WAMP2/V2/PubSub/WampRawTopicContainer.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Collections.Concurrent;
33
using System.Collections.Generic;
44
using System.Linq;
5+
using WampSharp.Core.Utilities;
56
using WampSharp.V2.Binding;
67
using WampSharp.V2.Core;
78
using WampSharp.V2.Core.Contracts;
@@ -96,8 +97,8 @@ private void OnTopicEmpty(object sender, EventArgs e)
9697
{
9798
if (!rawTopic.HasSubscribers)
9899
{
99-
mSubscriptionIdToTopic.TryRemove(rawTopic.SubscriptionId, out rawTopic);
100-
mTopicUriToTopic.TryRemove(rawTopic.CustomizedSubscriptionId, out rawTopic);
100+
mSubscriptionIdToTopic.TryRemoveExact(rawTopic.SubscriptionId, rawTopic);
101+
mTopicUriToTopic.TryRemoveExact(rawTopic.CustomizedSubscriptionId, rawTopic);
101102
rawTopic.Dispose();
102103
}
103104
}

src/net45/WampSharp/WAMP2/V2/Rpc/Dealer/MatchRpcOperationCatalog.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Collections.Concurrent;
33
using System.Collections.Generic;
44
using WampSharp.Core.Serialization;
5+
using WampSharp.Core.Utilities;
56
using WampSharp.V2.Core;
67
using WampSharp.V2.Core.Contracts;
78

@@ -69,9 +70,8 @@ private void OnRegistrationEmpty(object sender, EventArgs e)
6970
{
7071
if (!registration.HasOperations)
7172
{
72-
ProcedureRegistration removed;
73-
mRegistrationIdToRegistration.TryRemove(registration.RegistrationId, out removed);
74-
mProcedureToRegistration.TryRemove(registration.Procedure, out removed);
73+
mRegistrationIdToRegistration.TryRemoveExact(registration.RegistrationId, registration);
74+
mProcedureToRegistration.TryRemoveExact(registration.Procedure, registration);
7575
registration.Empty -= OnRegistrationEmpty;
7676
OnRegistrationRemoved(registration.Procedure);
7777
}

0 commit comments

Comments
 (0)