Skip to content

Commit 705097f

Browse files
authored
Merge pull request #2131 from JamesNK/jamesnk/update-2.54.0
2 parents 1412c31 + f9a00bc commit 705097f

28 files changed

+407
-149
lines changed

global.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
22
"sdk": {
3-
"version": "7.0.201"
3+
"version": "7.0.201",
4+
"rollForward": "latestFeature"
45
}
56
}

src/Grpc.AspNetCore.Server/Grpc.AspNetCore.Server.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
<Compile Include="..\Shared\Server\UnaryServerMethodInvoker.cs" Link="Model\Internal\UnaryServerMethodInvoker.cs" />
3131
<Compile Include="..\Shared\NullableAttributes.cs" Link="Internal\NullableAttributes.cs" />
3232
<Compile Include="..\Shared\CodeAnalysisAttributes.cs" Link="Internal\CodeAnalysisAttributes.cs" />
33+
<Compile Include="..\Shared\NonCapturingTimer.cs" Link="Internal\NonCapturingTimer.cs" />
3334
</ItemGroup>
3435

3536
<ItemGroup>

src/Grpc.AspNetCore.Server/Internal/ServerCallDeadlineManager.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#region Copyright notice and license
1+
#region Copyright notice and license
22

33
// Copyright 2019 The gRPC Authors
44
//
@@ -91,12 +91,12 @@ public ServerCallDeadlineManager(HttpContextServerCallContext serverCallContext,
9191
// Ensures there is no weird situation where the timer triggers
9292
// before the field is set. Shouldn't happen because only long deadlines
9393
// will take this path but better to be safe than sorry.
94-
_longDeadlineTimer = new Timer(DeadlineExceededLongDelegate, (this, maxTimerDueTime), Timeout.Infinite, Timeout.Infinite);
94+
_longDeadlineTimer = NonCapturingTimer.Create(DeadlineExceededLongDelegate, (this, maxTimerDueTime), Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan);
9595
_longDeadlineTimer.Change(timerMilliseconds, Timeout.Infinite);
9696
}
9797
else
9898
{
99-
_longDeadlineTimer = new Timer(DeadlineExceededDelegate, this, timerMilliseconds, Timeout.Infinite);
99+
_longDeadlineTimer = NonCapturingTimer.Create(DeadlineExceededDelegate, this, TimeSpan.FromMilliseconds(timerMilliseconds), Timeout.InfiniteTimeSpan);
100100
}
101101
}
102102

src/Grpc.Net.Client/Balancer/BalancerAttributes.cs

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#endregion
1818

1919
#if SUPPORT_LOAD_BALANCING
20+
using System.Collections;
2021
using System.Collections.Generic;
2122
using System.Collections.ObjectModel;
2223
using System.Diagnostics.CodeAnalysis;
@@ -29,7 +30,7 @@ namespace Grpc.Net.Client.Balancer;
2930
/// Note: Experimental API that can change or be removed without any prior notice.
3031
/// </para>
3132
/// </summary>
32-
public sealed class BalancerAttributes : IDictionary<string, object?>
33+
public sealed class BalancerAttributes : IDictionary<string, object?>, IReadOnlyDictionary<string, object?>
3334
{
3435
/// <summary>
3536
/// Gets a read-only collection of metadata attributes.
@@ -61,22 +62,28 @@ private BalancerAttributes(IDictionary<string, object?> attributes)
6162
_attributes[key] = value;
6263
}
6364
}
65+
6466
ICollection<string> IDictionary<string, object?>.Keys => _attributes.Keys;
6567
ICollection<object?> IDictionary<string, object?>.Values => _attributes.Values;
6668
int ICollection<KeyValuePair<string, object?>>.Count => _attributes.Count;
67-
bool ICollection<KeyValuePair<string, object?>>.IsReadOnly => ((IDictionary<string, object?>)_attributes).IsReadOnly;
69+
bool ICollection<KeyValuePair<string, object?>>.IsReadOnly => _attributes.IsReadOnly;
70+
IEnumerable<string> IReadOnlyDictionary<string, object?>.Keys => _attributes.Keys;
71+
IEnumerable<object?> IReadOnlyDictionary<string, object?>.Values => _attributes.Values;
72+
int IReadOnlyCollection<KeyValuePair<string, object?>>.Count => _attributes.Count;
73+
object? IReadOnlyDictionary<string, object?>.this[string key] => _attributes[key];
6874
void IDictionary<string, object?>.Add(string key, object? value) => _attributes.Add(key, value);
69-
void ICollection<KeyValuePair<string, object?>>.Add(KeyValuePair<string, object?> item) => ((IDictionary<string, object?>)_attributes).Add(item);
75+
void ICollection<KeyValuePair<string, object?>>.Add(KeyValuePair<string, object?> item) => _attributes.Add(item);
7076
void ICollection<KeyValuePair<string, object?>>.Clear() => _attributes.Clear();
71-
bool ICollection<KeyValuePair<string, object?>>.Contains(KeyValuePair<string, object?> item) => ((IDictionary<string, object?>)_attributes).Contains(item);
77+
bool ICollection<KeyValuePair<string, object?>>.Contains(KeyValuePair<string, object?> item) => _attributes.Contains(item);
7278
bool IDictionary<string, object?>.ContainsKey(string key) => _attributes.ContainsKey(key);
73-
void ICollection<KeyValuePair<string, object?>>.CopyTo(KeyValuePair<string, object?>[] array, int arrayIndex) =>
74-
((IDictionary<string, object?>)_attributes).CopyTo(array, arrayIndex);
79+
void ICollection<KeyValuePair<string, object?>>.CopyTo(KeyValuePair<string, object?>[] array, int arrayIndex) => _attributes.CopyTo(array, arrayIndex);
7580
IEnumerator<KeyValuePair<string, object?>> IEnumerable<KeyValuePair<string, object?>>.GetEnumerator() => _attributes.GetEnumerator();
76-
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => ((System.Collections.IEnumerable)_attributes).GetEnumerator();
81+
IEnumerator System.Collections.IEnumerable.GetEnumerator() => ((System.Collections.IEnumerable)_attributes).GetEnumerator();
7782
bool IDictionary<string, object?>.Remove(string key) => _attributes.Remove(key);
78-
bool ICollection<KeyValuePair<string, object?>>.Remove(KeyValuePair<string, object?> item) => ((IDictionary<string, object?>)_attributes).Remove(item);
83+
bool ICollection<KeyValuePair<string, object?>>.Remove(KeyValuePair<string, object?> item) => _attributes.Remove(item);
7984
bool IDictionary<string, object?>.TryGetValue(string key, out object? value) => _attributes.TryGetValue(key, out value);
85+
bool IReadOnlyDictionary<string, object?>.ContainsKey(string key) => _attributes.ContainsKey(key);
86+
bool IReadOnlyDictionary<string, object?>.TryGetValue(string key, out object? value) => _attributes.TryGetValue(key, out value);
8087

8188
/// <summary>
8289
/// Gets the value associated with the specified key.

src/Grpc.Net.Client/Balancer/DnsResolver.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ protected override void OnStarted()
6868

6969
if (_refreshInterval != Timeout.InfiniteTimeSpan)
7070
{
71-
_timer = new Timer(OnTimerCallback, null, Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan);
71+
_timer = NonCapturingTimer.Create(OnTimerCallback, state: null, Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan);
7272
_timer.Change(_refreshInterval, _refreshInterval);
7373
}
7474
}

src/Grpc.Net.Client/Balancer/Internal/SocketConnectivitySubchannelTransport.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#region Copyright notice and license
1+
#region Copyright notice and license
22

33
// Copyright 2019 The gRPC Authors
44
//
@@ -77,7 +77,7 @@ public SocketConnectivitySubchannelTransport(
7777
ConnectTimeout = connectTimeout;
7878
_socketConnect = socketConnect ?? OnConnect;
7979
_activeStreams = new List<ActiveStream>();
80-
_socketConnectedTimer = new Timer(OnCheckSocketConnection, state: null, Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan);
80+
_socketConnectedTimer = NonCapturingTimer.Create(OnCheckSocketConnection, state: null, Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan);
8181
}
8282

8383
private object Lock => _subchannel.Lock;

src/Grpc.Net.Client/Balancer/PollingResolver.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#region Copyright notice and license
1+
#region Copyright notice and license
22

33
// Copyright 2019 The gRPC Authors
44
//
@@ -86,7 +86,7 @@ protected PollingResolver(ILoggerFactory loggerFactory, IBackoffPolicyFactory? b
8686
/// </para>
8787
/// </summary>
8888
/// <param name="listener">The callback used to receive updates on the target.</param>
89-
public override sealed void Start(Action<ResolverResult> listener)
89+
public sealed override void Start(Action<ResolverResult> listener)
9090
{
9191
if (listener == null)
9292
{

src/Grpc.Net.Client/Balancer/Subchannel.cs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#region Copyright notice and license
1+
#region Copyright notice and license
22

33
// Copyright 2019 The gRPC Authors
44
//
@@ -233,7 +233,21 @@ public void RequestConnection()
233233
}
234234
}
235235

236-
_ = ConnectTransportAsync();
236+
// Don't capture the current ExecutionContext and its AsyncLocals onto the connect
237+
bool restoreFlow = false;
238+
if (!ExecutionContext.IsFlowSuppressed())
239+
{
240+
ExecutionContext.SuppressFlow();
241+
restoreFlow = true;
242+
}
243+
244+
_ = Task.Run(ConnectTransportAsync);
245+
246+
// Restore the current ExecutionContext
247+
if (restoreFlow)
248+
{
249+
ExecutionContext.RestoreFlow();
250+
}
237251
}
238252

239253
private void CancelInProgressConnect()

src/Grpc.Net.Client/Grpc.Net.Client.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
44
<Description>.NET client for gRPC</Description>
@@ -35,6 +35,7 @@
3535
<Compile Include="..\Shared\NullableAttributes.cs" Link="Internal\NullableAttributes.cs" />
3636
<Compile Include="..\Shared\Http2ErrorCode.cs" Link="Internal\Http2ErrorCode.cs" />
3737
<Compile Include="..\Shared\Http3ErrorCode.cs" Link="Internal\Http3ErrorCode.cs" />
38+
<Compile Include="..\Shared\NonCapturingTimer.cs" Link="Internal\NonCapturingTimer.cs" />
3839
<Compile Include="..\Shared\NonDisposableMemoryStream.cs" Link="Internal\NonDisposableMemoryStream.cs" />
3940
</ItemGroup>
4041

src/Grpc.Net.Client/GrpcChannel.cs

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,7 @@ public sealed class GrpcChannel : ChannelBase, IDisposable
5454
private readonly Dictionary<MethodKey, MethodConfig>? _serviceConfigMethods;
5555
private readonly bool _isSecure;
5656
private readonly List<CallCredentials>? _callCredentials;
57-
// Internal for testing
58-
internal readonly HashSet<IDisposable> ActiveCalls;
57+
private readonly HashSet<IDisposable> _activeCalls;
5958

6059
internal Uri Address { get; }
6160
internal HttpMessageInvoker HttpInvoker { get; }
@@ -165,7 +164,7 @@ internal GrpcChannel(Uri address, GrpcChannelOptions channelOptions) : base(addr
165164
ThrowOperationCanceledOnCancellation = channelOptions.ThrowOperationCanceledOnCancellation;
166165
UnsafeUseInsecureChannelCallCredentials = channelOptions.UnsafeUseInsecureChannelCallCredentials;
167166
_createMethodInfoFunc = CreateMethodInfo;
168-
ActiveCalls = new HashSet<IDisposable>();
167+
_activeCalls = new HashSet<IDisposable>();
169168
if (channelOptions.ServiceConfig is { } serviceConfig)
170169
{
171170
RetryThrottling = serviceConfig.RetryThrottling != null ? CreateChannelRetryThrottling(serviceConfig.RetryThrottling) : null;
@@ -490,15 +489,15 @@ internal void RegisterActiveCall(IDisposable grpcCall)
490489
throw new ObjectDisposedException(nameof(GrpcChannel));
491490
}
492491

493-
ActiveCalls.Add(grpcCall);
492+
_activeCalls.Add(grpcCall);
494493
}
495494
}
496495

497496
internal void FinishActiveCall(IDisposable grpcCall)
498497
{
499498
lock (_lock)
500499
{
501-
ActiveCalls.Remove(grpcCall);
500+
_activeCalls.Remove(grpcCall);
502501
}
503502
}
504503

@@ -749,9 +748,9 @@ public void Dispose()
749748
return;
750749
}
751750

752-
if (ActiveCalls.Count > 0)
751+
if (_activeCalls.Count > 0)
753752
{
754-
activeCallsCopy = ActiveCalls.ToArray();
753+
activeCallsCopy = _activeCalls.ToArray();
755754
}
756755

757756
Disposed = true;
@@ -807,6 +806,15 @@ internal int GetRandomNumber(int minValue, int maxValue)
807806
}
808807
}
809808

809+
// Internal for testing
810+
internal IDisposable[] GetActiveCalls()
811+
{
812+
lock (_lock)
813+
{
814+
return _activeCalls.ToArray();
815+
}
816+
}
817+
810818
#if SUPPORT_LOAD_BALANCING
811819
private sealed class SubChannelTransportFactory : ISubchannelTransportFactory
812820
{

0 commit comments

Comments
 (0)