aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/csharp/Grpc.Core
diff options
context:
space:
mode:
Diffstat (limited to 'src/csharp/Grpc.Core')
-rw-r--r--src/csharp/Grpc.Core/Channel.cs2
-rw-r--r--src/csharp/Grpc.Core/ChannelCredentials.cs39
-rw-r--r--src/csharp/Grpc.Core/Internal/AsyncCall.cs29
-rw-r--r--src/csharp/Grpc.Core/Internal/AsyncCallBase.cs32
-rw-r--r--src/csharp/Grpc.Core/Internal/AsyncCallServer.cs10
-rw-r--r--src/csharp/Grpc.Core/Internal/BatchContextSafeHandle.cs2
-rw-r--r--src/csharp/Grpc.Core/Internal/GrpcThreadPool.cs4
-rw-r--r--src/csharp/Grpc.Core/Internal/RequestCallContextSafeHandle.cs2
-rw-r--r--src/csharp/Grpc.Core/Metadata.cs4
-rwxr-xr-xsrc/csharp/Grpc.Core/Version.csproj.include2
-rw-r--r--src/csharp/Grpc.Core/VersionInfo.cs4
11 files changed, 101 insertions, 29 deletions
diff --git a/src/csharp/Grpc.Core/Channel.cs b/src/csharp/Grpc.Core/Channel.cs
index e9930b6fbc..7912b06b71 100644
--- a/src/csharp/Grpc.Core/Channel.cs
+++ b/src/csharp/Grpc.Core/Channel.cs
@@ -72,9 +72,9 @@ namespace Grpc.Core
this.environment = GrpcEnvironment.AddRef();
this.completionQueue = this.environment.PickCompletionQueue();
- using (var nativeCredentials = credentials.ToNativeCredentials())
using (var nativeChannelArgs = ChannelOptions.CreateChannelArgs(this.options.Values))
{
+ var nativeCredentials = credentials.GetNativeCredentials();
if (nativeCredentials != null)
{
this.handle = ChannelSafeHandle.CreateSecure(nativeCredentials, target, nativeChannelArgs);
diff --git a/src/csharp/Grpc.Core/ChannelCredentials.cs b/src/csharp/Grpc.Core/ChannelCredentials.cs
index ba482897d7..3ce32f31b7 100644
--- a/src/csharp/Grpc.Core/ChannelCredentials.cs
+++ b/src/csharp/Grpc.Core/ChannelCredentials.cs
@@ -31,6 +31,19 @@ namespace Grpc.Core
public abstract class ChannelCredentials
{
static readonly ChannelCredentials InsecureInstance = new InsecureCredentialsImpl();
+ readonly Lazy<ChannelCredentialsSafeHandle> cachedNativeCredentials;
+
+ /// <summary>
+ /// Creates a new instance of channel credentials
+ /// </summary>
+ public ChannelCredentials()
+ {
+ // Native credentials object need to be kept alive once initialized for subchannel sharing to work correctly
+ // with secure connections. See https://github.com/grpc/grpc/issues/15207.
+ // We rely on finalizer to clean up the native portion of ChannelCredentialsSafeHandle after the ChannelCredentials
+ // instance becomes unused.
+ this.cachedNativeCredentials = new Lazy<ChannelCredentialsSafeHandle>(() => CreateNativeCredentials());
+ }
/// <summary>
/// Returns instance of credentials that provides no security and
@@ -57,11 +70,22 @@ namespace Grpc.Core
}
/// <summary>
- /// Creates native object for the credentials. May return null if insecure channel
- /// should be created.
+ /// Gets native object for the credentials, creating one if it already doesn't exist. May return null if insecure channel
+ /// should be created. Caller must not call <c>Dispose()</c> on the returned native credentials as their lifetime
+ /// is managed by this class (and instances of native credentials are cached).
+ /// </summary>
+ /// <returns>The native credentials.</returns>
+ internal ChannelCredentialsSafeHandle GetNativeCredentials()
+ {
+ return cachedNativeCredentials.Value;
+ }
+
+ /// <summary>
+ /// Creates a new native object for the credentials. May return null if insecure channel
+ /// should be created. For internal use only, use <see cref="GetNativeCredentials"/> instead.
/// </summary>
/// <returns>The native credentials.</returns>
- internal abstract ChannelCredentialsSafeHandle ToNativeCredentials();
+ internal abstract ChannelCredentialsSafeHandle CreateNativeCredentials();
/// <summary>
/// Returns <c>true</c> if this credential type allows being composed by <c>CompositeCredentials</c>.
@@ -73,7 +97,7 @@ namespace Grpc.Core
private sealed class InsecureCredentialsImpl : ChannelCredentials
{
- internal override ChannelCredentialsSafeHandle ToNativeCredentials()
+ internal override ChannelCredentialsSafeHandle CreateNativeCredentials()
{
return null;
}
@@ -145,7 +169,7 @@ namespace Grpc.Core
get { return true; }
}
- internal override ChannelCredentialsSafeHandle ToNativeCredentials()
+ internal override ChannelCredentialsSafeHandle CreateNativeCredentials()
{
return ChannelCredentialsSafeHandle.CreateSslCredentials(rootCertificates, keyCertificatePair);
}
@@ -173,12 +197,11 @@ namespace Grpc.Core
GrpcPreconditions.CheckArgument(channelCredentials.IsComposable, "Supplied channel credentials do not allow composition.");
}
- internal override ChannelCredentialsSafeHandle ToNativeCredentials()
+ internal override ChannelCredentialsSafeHandle CreateNativeCredentials()
{
- using (var channelCreds = channelCredentials.ToNativeCredentials())
using (var callCreds = callCredentials.ToNativeCredentials())
{
- var nativeComposite = ChannelCredentialsSafeHandle.CreateComposite(channelCreds, callCreds);
+ var nativeComposite = ChannelCredentialsSafeHandle.CreateComposite(channelCredentials.GetNativeCredentials(), callCreds);
if (nativeComposite.IsInvalid)
{
throw new ArgumentException("Error creating native composite credentials. Likely, this is because you are trying to compose incompatible credentials.");
diff --git a/src/csharp/Grpc.Core/Internal/AsyncCall.cs b/src/csharp/Grpc.Core/Internal/AsyncCall.cs
index 9946d1a6cf..66902f3caa 100644
--- a/src/csharp/Grpc.Core/Internal/AsyncCall.cs
+++ b/src/csharp/Grpc.Core/Internal/AsyncCall.cs
@@ -108,7 +108,7 @@ namespace Grpc.Core.Internal
}
catch (Exception e)
{
- Logger.Error(e, "Exception occured while invoking completion delegate.");
+ Logger.Error(e, "Exception occurred while invoking completion delegate.");
}
}
finally
@@ -325,9 +325,18 @@ namespace Grpc.Core.Internal
}
}
- protected override void OnAfterReleaseResources()
+ protected override void OnAfterReleaseResourcesLocked()
{
details.Channel.RemoveCallReference(this);
+ }
+
+ protected override void OnAfterReleaseResourcesUnlocked()
+ {
+ // If cancellation callback is in progress, this can block
+ // so we need to do this outside of call's lock to prevent
+ // deadlock.
+ // See https://github.com/grpc/grpc/issues/14777
+ // See https://github.com/dotnet/corefx/issues/14903
cancellationTokenRegistration?.Dispose();
}
@@ -448,6 +457,7 @@ namespace Grpc.Core.Internal
TResponse msg = default(TResponse);
var deserializeException = TryDeserialize(receivedMessage, out msg);
+ bool releasedResources;
lock (myLock)
{
finished = true;
@@ -464,7 +474,12 @@ namespace Grpc.Core.Internal
streamingWriteTcs = null;
}
- ReleaseResourcesIfPossible();
+ releasedResources = ReleaseResourcesIfPossible();
+ }
+
+ if (releasedResources)
+ {
+ OnAfterReleaseResourcesUnlocked();
}
responseHeadersTcs.SetResult(responseHeaders);
@@ -494,6 +509,7 @@ namespace Grpc.Core.Internal
TaskCompletionSource<object> delayedStreamingWriteTcs = null;
+ bool releasedResources;
lock (myLock)
{
finished = true;
@@ -504,7 +520,12 @@ namespace Grpc.Core.Internal
streamingWriteTcs = null;
}
- ReleaseResourcesIfPossible();
+ releasedResources = ReleaseResourcesIfPossible();
+ }
+
+ if (releasedResources)
+ {
+ OnAfterReleaseResourcesUnlocked();
}
if (delayedStreamingWriteTcs != null)
diff --git a/src/csharp/Grpc.Core/Internal/AsyncCallBase.cs b/src/csharp/Grpc.Core/Internal/AsyncCallBase.cs
index 3273c26b88..5a53049e4b 100644
--- a/src/csharp/Grpc.Core/Internal/AsyncCallBase.cs
+++ b/src/csharp/Grpc.Core/Internal/AsyncCallBase.cs
@@ -196,10 +196,14 @@ namespace Grpc.Core.Internal
call.Dispose();
}
disposed = true;
- OnAfterReleaseResources();
+ OnAfterReleaseResourcesLocked();
}
- protected virtual void OnAfterReleaseResources()
+ protected virtual void OnAfterReleaseResourcesLocked()
+ {
+ }
+
+ protected virtual void OnAfterReleaseResourcesUnlocked()
{
}
@@ -235,6 +239,7 @@ namespace Grpc.Core.Internal
{
bool delayCompletion = false;
TaskCompletionSource<object> origTcs = null;
+ bool releasedResources;
lock (myLock)
{
if (!success && !finished && IsClient) {
@@ -252,7 +257,12 @@ namespace Grpc.Core.Internal
streamingWriteTcs = null;
}
- ReleaseResourcesIfPossible();
+ releasedResources = ReleaseResourcesIfPossible();
+ }
+
+ if (releasedResources)
+ {
+ OnAfterReleaseResourcesUnlocked();
}
if (!success)
@@ -282,9 +292,15 @@ namespace Grpc.Core.Internal
/// </summary>
protected void HandleSendStatusFromServerFinished(bool success)
{
+ bool releasedResources;
lock (myLock)
{
- ReleaseResourcesIfPossible();
+ releasedResources = ReleaseResourcesIfPossible();
+ }
+
+ if (releasedResources)
+ {
+ OnAfterReleaseResourcesUnlocked();
}
if (!success)
@@ -310,6 +326,7 @@ namespace Grpc.Core.Internal
var deserializeException = (success && receivedMessage != null) ? TryDeserialize(receivedMessage, out msg) : null;
TaskCompletionSource<TRead> origTcs = null;
+ bool releasedResources;
lock (myLock)
{
origTcs = streamingReadTcs;
@@ -332,7 +349,12 @@ namespace Grpc.Core.Internal
streamingReadTcs = null;
}
- ReleaseResourcesIfPossible();
+ releasedResources = ReleaseResourcesIfPossible();
+ }
+
+ if (releasedResources)
+ {
+ OnAfterReleaseResourcesUnlocked();
}
if (deserializeException != null && !IsClient)
diff --git a/src/csharp/Grpc.Core/Internal/AsyncCallServer.cs b/src/csharp/Grpc.Core/Internal/AsyncCallServer.cs
index 11acb27533..0ceca4abb8 100644
--- a/src/csharp/Grpc.Core/Internal/AsyncCallServer.cs
+++ b/src/csharp/Grpc.Core/Internal/AsyncCallServer.cs
@@ -184,7 +184,7 @@ namespace Grpc.Core.Internal
throw new InvalidOperationException("Call be only called for client calls");
}
- protected override void OnAfterReleaseResources()
+ protected override void OnAfterReleaseResourcesLocked()
{
server.RemoveCallReference(this);
}
@@ -206,6 +206,7 @@ namespace Grpc.Core.Internal
{
// NOTE: because this event is a result of batch containing GRPC_OP_RECV_CLOSE_ON_SERVER,
// success will be always set to true.
+ bool releasedResources;
lock (myLock)
{
finished = true;
@@ -217,7 +218,12 @@ namespace Grpc.Core.Internal
streamingReadTcs = new TaskCompletionSource<TRequest>();
streamingReadTcs.SetResult(default(TRequest));
}
- ReleaseResourcesIfPossible();
+ releasedResources = ReleaseResourcesIfPossible();
+ }
+
+ if (releasedResources)
+ {
+ OnAfterReleaseResourcesUnlocked();
}
if (cancelled)
diff --git a/src/csharp/Grpc.Core/Internal/BatchContextSafeHandle.cs b/src/csharp/Grpc.Core/Internal/BatchContextSafeHandle.cs
index 53a859d18f..085e7faf59 100644
--- a/src/csharp/Grpc.Core/Internal/BatchContextSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/BatchContextSafeHandle.cs
@@ -144,7 +144,7 @@ namespace Grpc.Core.Internal
}
catch (Exception e)
{
- Logger.Error(e, "Exception occured while invoking batch completion delegate.");
+ Logger.Error(e, "Exception occurred while invoking batch completion delegate.");
}
finally
{
diff --git a/src/csharp/Grpc.Core/Internal/GrpcThreadPool.cs b/src/csharp/Grpc.Core/Internal/GrpcThreadPool.cs
index 8ddda9be5c..622cfde9e7 100644
--- a/src/csharp/Grpc.Core/Internal/GrpcThreadPool.cs
+++ b/src/csharp/Grpc.Core/Internal/GrpcThreadPool.cs
@@ -189,7 +189,7 @@ namespace Grpc.Core.Internal
}
catch (Exception e)
{
- Logger.Error(e, "Exception occured while extracting event from completion registry.");
+ Logger.Error(e, "Exception occurred while extracting event from completion registry.");
}
}
}
@@ -233,7 +233,7 @@ namespace Grpc.Core.Internal
}
catch (Exception e)
{
- Logger.Error(e, "Exception occured while invoking completion delegate");
+ Logger.Error(e, "Exception occurred while invoking completion delegate");
}
finally
{
diff --git a/src/csharp/Grpc.Core/Internal/RequestCallContextSafeHandle.cs b/src/csharp/Grpc.Core/Internal/RequestCallContextSafeHandle.cs
index ebc2d6d8d6..24fde75e5a 100644
--- a/src/csharp/Grpc.Core/Internal/RequestCallContextSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/RequestCallContextSafeHandle.cs
@@ -112,7 +112,7 @@ namespace Grpc.Core.Internal
}
catch (Exception e)
{
- Logger.Error(e, "Exception occured while invoking request call completion delegate.");
+ Logger.Error(e, "Exception occurred while invoking request call completion delegate.");
}
finally
{
diff --git a/src/csharp/Grpc.Core/Metadata.cs b/src/csharp/Grpc.Core/Metadata.cs
index 0e4456278c..281952d6d4 100644
--- a/src/csharp/Grpc.Core/Metadata.cs
+++ b/src/csharp/Grpc.Core/Metadata.cs
@@ -225,7 +225,7 @@ namespace Grpc.Core
/// </summary>
public class Entry
{
- private static readonly Regex ValidKeyRegex = new Regex("^[a-z0-9_-]+$");
+ private static readonly Regex ValidKeyRegex = new Regex("^[.a-z0-9_-]+$");
readonly string key;
readonly string value;
@@ -360,7 +360,7 @@ namespace Grpc.Core
{
var normalized = GrpcPreconditions.CheckNotNull(key, "key").ToLowerInvariant();
GrpcPreconditions.CheckArgument(ValidKeyRegex.IsMatch(normalized),
- "Metadata entry key not valid. Keys can only contain lowercase alphanumeric characters, underscores and hyphens.");
+ "Metadata entry key not valid. Keys can only contain lowercase alphanumeric characters, underscores, hyphens and dots.");
return normalized;
}
diff --git a/src/csharp/Grpc.Core/Version.csproj.include b/src/csharp/Grpc.Core/Version.csproj.include
index 45bd8ebd85..18515ea1e8 100755
--- a/src/csharp/Grpc.Core/Version.csproj.include
+++ b/src/csharp/Grpc.Core/Version.csproj.include
@@ -1,7 +1,7 @@
<!-- This file is generated -->
<Project>
<PropertyGroup>
- <GrpcCsharpVersion>1.15.0-dev</GrpcCsharpVersion>
+ <GrpcCsharpVersion>1.16.0-dev</GrpcCsharpVersion>
<GoogleProtobufVersion>3.6.1</GoogleProtobufVersion>
</PropertyGroup>
</Project>
diff --git a/src/csharp/Grpc.Core/VersionInfo.cs b/src/csharp/Grpc.Core/VersionInfo.cs
index 295e0f2577..55d09dda7a 100644
--- a/src/csharp/Grpc.Core/VersionInfo.cs
+++ b/src/csharp/Grpc.Core/VersionInfo.cs
@@ -33,11 +33,11 @@ namespace Grpc.Core
/// <summary>
/// Current <c>AssemblyFileVersion</c> of gRPC C# assemblies
/// </summary>
- public const string CurrentAssemblyFileVersion = "1.15.0.0";
+ public const string CurrentAssemblyFileVersion = "1.16.0.0";
/// <summary>
/// Current version of gRPC C#
/// </summary>
- public const string CurrentVersion = "1.15.0-dev";
+ public const string CurrentVersion = "1.16.0-dev";
}
}