diff options
Diffstat (limited to 'src/csharp')
-rw-r--r-- | src/csharp/Grpc.Core.Tests/NUnitMain.cs | 2 | ||||
-rw-r--r-- | src/csharp/Grpc.Core/Grpc.Core.targets | 8 | ||||
-rw-r--r-- | src/csharp/Grpc.Core/GrpcEnvironment.cs | 2 | ||||
-rw-r--r-- | src/csharp/Grpc.Core/Internal/AtomicCounter.cs | 2 | ||||
-rw-r--r-- | src/csharp/Grpc.Core/Internal/GrpcThreadPool.cs | 37 | ||||
-rw-r--r-- | src/csharp/Grpc.Core/Logging/LogLevel.cs | 6 | ||||
-rw-r--r-- | src/csharp/Grpc.Core/Logging/LogLevelFilterLogger.cs | 43 | ||||
-rwxr-xr-x | src/csharp/Grpc.Core/Version.csproj.include | 2 | ||||
-rw-r--r-- | src/csharp/Grpc.Core/VersionInfo.cs | 4 | ||||
-rw-r--r-- | src/csharp/Grpc.Examples.Tests/NUnitMain.cs | 2 | ||||
-rw-r--r-- | src/csharp/Grpc.HealthCheck.Tests/NUnitMain.cs | 2 | ||||
-rw-r--r-- | src/csharp/Grpc.IntegrationTesting/NUnitMain.cs | 2 | ||||
-rw-r--r-- | src/csharp/Grpc.Microbenchmarks/Program.cs | 2 | ||||
-rw-r--r-- | src/csharp/Grpc.Reflection.Tests/NUnitMain.cs | 2 | ||||
-rwxr-xr-x | src/csharp/build_packages_dotnetcli.bat | 2 | ||||
-rwxr-xr-x | src/csharp/build_packages_dotnetcli.sh | 4 |
16 files changed, 102 insertions, 20 deletions
diff --git a/src/csharp/Grpc.Core.Tests/NUnitMain.cs b/src/csharp/Grpc.Core.Tests/NUnitMain.cs index 87972e23ad..49cb8cd3b9 100644 --- a/src/csharp/Grpc.Core.Tests/NUnitMain.cs +++ b/src/csharp/Grpc.Core.Tests/NUnitMain.cs @@ -33,7 +33,7 @@ namespace Grpc.Core.Tests public static int Main(string[] args) { // Make logger immune to NUnit capturing stdout and stderr to workaround https://github.com/nunit/nunit/issues/1406. - GrpcEnvironment.SetLogger(new TextWriterLogger(Console.Error)); + GrpcEnvironment.SetLogger(new ConsoleLogger()); #if NETCOREAPP1_0 return new AutoRun(typeof(NUnitMain).GetTypeInfo().Assembly).Execute(args, new ExtendedTextWrapper(Console.Out), Console.In); #else diff --git a/src/csharp/Grpc.Core/Grpc.Core.targets b/src/csharp/Grpc.Core/Grpc.Core.targets index 3367d51a80..cce53db82b 100644 --- a/src/csharp/Grpc.Core/Grpc.Core.targets +++ b/src/csharp/Grpc.Core/Grpc.Core.targets @@ -4,26 +4,32 @@ <Content Include="$(MSBuildThisFileDirectory)..\..\runtimes\win\native\grpc_csharp_ext.x86.dll"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <Link>grpc_csharp_ext.x86.dll</Link> + <Visible>false</Visible> </Content> <Content Include="$(MSBuildThisFileDirectory)..\..\runtimes\win\native\grpc_csharp_ext.x64.dll"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <Link>grpc_csharp_ext.x64.dll</Link> + <Visible>false</Visible> </Content> <Content Include="$(MSBuildThisFileDirectory)..\..\runtimes\linux\native\libgrpc_csharp_ext.x86.so"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <Link>libgrpc_csharp_ext.x86.so</Link> + <Visible>false</Visible> </Content> <Content Include="$(MSBuildThisFileDirectory)..\..\runtimes\linux\native\libgrpc_csharp_ext.x64.so"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <Link>libgrpc_csharp_ext.x64.so</Link> + <Visible>false</Visible> </Content> <Content Include="$(MSBuildThisFileDirectory)..\..\runtimes\osx\native\libgrpc_csharp_ext.x86.dylib"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <Link>libgrpc_csharp_ext.x86.dylib</Link> + <Visible>false</Visible> </Content> <Content Include="$(MSBuildThisFileDirectory)..\..\runtimes\osx\native\libgrpc_csharp_ext.x64.dylib"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <Link>libgrpc_csharp_ext.x64.dylib</Link> + <Visible>false</Visible> </Content> </ItemGroup> -</Project>
\ No newline at end of file +</Project> diff --git a/src/csharp/Grpc.Core/GrpcEnvironment.cs b/src/csharp/Grpc.Core/GrpcEnvironment.cs index cbc7d2078c..80031cb7ef 100644 --- a/src/csharp/Grpc.Core/GrpcEnvironment.cs +++ b/src/csharp/Grpc.Core/GrpcEnvironment.cs @@ -43,7 +43,7 @@ namespace Grpc.Core static readonly HashSet<Channel> registeredChannels = new HashSet<Channel>(); static readonly HashSet<Server> registeredServers = new HashSet<Server>(); - static ILogger logger = new NullLogger(); + static ILogger logger = new LogLevelFilterLogger(new ConsoleLogger(), LogLevel.Off, true); readonly GrpcThreadPool threadPool; readonly DebugStats debugStats = new DebugStats(); diff --git a/src/csharp/Grpc.Core/Internal/AtomicCounter.cs b/src/csharp/Grpc.Core/Internal/AtomicCounter.cs index 64e16e4c54..20e25f9d88 100644 --- a/src/csharp/Grpc.Core/Internal/AtomicCounter.cs +++ b/src/csharp/Grpc.Core/Internal/AtomicCounter.cs @@ -64,7 +64,7 @@ namespace Grpc.Core.Internal { get { - return counter; + return Interlocked.Read(ref counter); } } } diff --git a/src/csharp/Grpc.Core/Internal/GrpcThreadPool.cs b/src/csharp/Grpc.Core/Internal/GrpcThreadPool.cs index 19b44c2618..3c94b602c0 100644 --- a/src/csharp/Grpc.Core/Internal/GrpcThreadPool.cs +++ b/src/csharp/Grpc.Core/Internal/GrpcThreadPool.cs @@ -33,8 +33,8 @@ namespace Grpc.Core.Internal internal class GrpcThreadPool { static readonly ILogger Logger = GrpcEnvironment.Logger.ForType<GrpcThreadPool>(); - static readonly WaitCallback RunCompletionQueueEventCallbackSuccess = new WaitCallback((callback) => RunCompletionQueueEventCallback((OpCompletionDelegate) callback, true)); - static readonly WaitCallback RunCompletionQueueEventCallbackFailure = new WaitCallback((callback) => RunCompletionQueueEventCallback((OpCompletionDelegate) callback, false)); + const int FinishContinuationsSleepMillis = 10; + const int MaxFinishContinuationsSleepTotalMillis = 10000; readonly GrpcEnvironment environment; readonly object myLock = new object(); @@ -42,6 +42,9 @@ namespace Grpc.Core.Internal readonly int poolSize; readonly int completionQueueCount; readonly bool inlineHandlers; + readonly WaitCallback runCompletionQueueEventCallbackSuccess; + readonly WaitCallback runCompletionQueueEventCallbackFailure; + readonly AtomicCounter queuedContinuationCounter = new AtomicCounter(); readonly List<BasicProfiler> threadProfilers = new List<BasicProfiler>(); // profilers assigned to threadpool threads @@ -64,6 +67,9 @@ namespace Grpc.Core.Internal this.inlineHandlers = inlineHandlers; GrpcPreconditions.CheckArgument(poolSize >= completionQueueCount, "Thread pool size cannot be smaller than the number of completion queues used."); + + this.runCompletionQueueEventCallbackSuccess = new WaitCallback((callback) => RunCompletionQueueEventCallback((OpCompletionDelegate) callback, true)); + this.runCompletionQueueEventCallbackFailure = new WaitCallback((callback) => RunCompletionQueueEventCallback((OpCompletionDelegate) callback, false)); } public void Start() @@ -173,7 +179,8 @@ namespace Grpc.Core.Internal // Use cached delegates to avoid unnecessary allocations if (!inlineHandlers) { - ThreadPool.QueueUserWorkItem(success ? RunCompletionQueueEventCallbackSuccess : RunCompletionQueueEventCallbackFailure, callback); + queuedContinuationCounter.Increment(); + ThreadPool.QueueUserWorkItem(success ? runCompletionQueueEventCallbackSuccess : runCompletionQueueEventCallbackFailure, callback); } else { @@ -187,6 +194,24 @@ namespace Grpc.Core.Internal } } while (ev.type != CompletionQueueEvent.CompletionType.Shutdown); + + // Continuations are running on default threadpool that consists of background threads. + // GrpcThreadPool thread (a foreground thread) will not exit unless all queued work had + // been finished to prevent terminating the continuations queued prematurely. + int sleepIterations = 0; + while (queuedContinuationCounter.Count != 0) + { + // Only happens on shutdown and having pending continuations shouldn't very common, + // so sleeping here for a little bit is fine. + if (sleepIterations >= MaxFinishContinuationsSleepTotalMillis / FinishContinuationsSleepMillis) + { + Logger.Warning("Shutting down gRPC thread [{0}] with unfinished callbacks (Timed out waiting for callbacks to finish).", + Thread.CurrentThread.Name); + break; + } + Thread.Sleep(FinishContinuationsSleepMillis); + sleepIterations ++; + } } private static IReadOnlyCollection<CompletionQueueSafeHandle> CreateCompletionQueueList(GrpcEnvironment environment, int completionQueueCount) @@ -200,7 +225,7 @@ namespace Grpc.Core.Internal return list.AsReadOnly(); } - private static void RunCompletionQueueEventCallback(OpCompletionDelegate callback, bool success) + private void RunCompletionQueueEventCallback(OpCompletionDelegate callback, bool success) { try { @@ -210,6 +235,10 @@ namespace Grpc.Core.Internal { Logger.Error(e, "Exception occured while invoking completion delegate"); } + finally + { + queuedContinuationCounter.Decrement(); + } } } } diff --git a/src/csharp/Grpc.Core/Logging/LogLevel.cs b/src/csharp/Grpc.Core/Logging/LogLevel.cs index 7718e3c2ab..4db0e47b97 100644 --- a/src/csharp/Grpc.Core/Logging/LogLevel.cs +++ b/src/csharp/Grpc.Core/Logging/LogLevel.cs @@ -39,6 +39,10 @@ namespace Grpc.Core.Logging /// <summary> /// Error severity. /// </summary> - Error + Error, + /// <summary> + /// Logging is off. + /// </summary> + Off = int.MaxValue } } diff --git a/src/csharp/Grpc.Core/Logging/LogLevelFilterLogger.cs b/src/csharp/Grpc.Core/Logging/LogLevelFilterLogger.cs index b611c191a5..a650d029d7 100644 --- a/src/csharp/Grpc.Core/Logging/LogLevelFilterLogger.cs +++ b/src/csharp/Grpc.Core/Logging/LogLevelFilterLogger.cs @@ -27,6 +27,8 @@ namespace Grpc.Core.Logging /// <summary>Logger that filters out messages below certain log level.</summary> public class LogLevelFilterLogger : ILogger { + // Verbosity environment variable used by C core. + private const string CoreVerbosityEnvVarName = "GRPC_VERBOSITY"; readonly ILogger innerLogger; readonly LogLevel logLevel; @@ -40,6 +42,19 @@ namespace Grpc.Core.Logging } /// <summary> + /// Creates and instance of <c>LogLevelFilter.</c> + /// The <c>fromEnvironmentVariable</c> parameter allows looking up "GRPC_VERBOSITY" setting provided by C-core + /// and uses the same log level for C# logs. Using this setting is recommended as it can prevent unintentionally hiding + /// C core logs requested by "GRPC_VERBOSITY" environment variable (which could happen if C# logger's log level was set to a more restrictive value). + /// </summary> + /// <param name="logger">the logger to forward filtered logs to.</param> + /// <param name="defaultLogLevel">the default log level, unless overriden by env variable.</param> + /// <param name="fromEnvironmentVariable">if <c>true</c>, override log level with setting from environment variable.</param> + public LogLevelFilterLogger(ILogger logger, LogLevel defaultLogLevel, bool fromEnvironmentVariable) : this(logger, GetLogLevelFromEnvironment(defaultLogLevel, fromEnvironmentVariable)) + { + } + + /// <summary> /// Returns a logger associated with the specified type. /// </summary> public virtual ILogger ForType<T>() @@ -141,5 +156,33 @@ namespace Grpc.Core.Logging innerLogger.Error(exception, message); } } + + /// <summary>Get log level based on a default and lookup of <c>GRPC_VERBOSITY</c> environment variable.</summary> + private static LogLevel GetLogLevelFromEnvironment(LogLevel defaultLogLevel, bool fromEnvironmentVariable) + { + if (!fromEnvironmentVariable) + { + return defaultLogLevel; + } + + var verbosityString = System.Environment.GetEnvironmentVariable(CoreVerbosityEnvVarName); + if (verbosityString == null) + { + return defaultLogLevel; + } + + // NOTE: C core doesn't have "WARNING" log level + switch (verbosityString.ToUpperInvariant()) + { + case "DEBUG": + return LogLevel.Debug; + case "INFO": + return LogLevel.Info; + case "ERROR": + return LogLevel.Error; + default: + return defaultLogLevel; + } + } } } diff --git a/src/csharp/Grpc.Core/Version.csproj.include b/src/csharp/Grpc.Core/Version.csproj.include index 81156452f3..124ecab14c 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.5.0-dev</GrpcCsharpVersion> + <GrpcCsharpVersion>1.7.0-dev</GrpcCsharpVersion> <GoogleProtobufVersion>3.3.0</GoogleProtobufVersion> </PropertyGroup> </Project> diff --git a/src/csharp/Grpc.Core/VersionInfo.cs b/src/csharp/Grpc.Core/VersionInfo.cs index 92aa0e5aed..588cc84516 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.5.0.0"; + public const string CurrentAssemblyFileVersion = "1.7.0.0"; /// <summary> /// Current version of gRPC C# /// </summary> - public const string CurrentVersion = "1.5.0-dev"; + public const string CurrentVersion = "1.7.0-dev"; } } diff --git a/src/csharp/Grpc.Examples.Tests/NUnitMain.cs b/src/csharp/Grpc.Examples.Tests/NUnitMain.cs index a83caea206..bcb8b46b64 100644 --- a/src/csharp/Grpc.Examples.Tests/NUnitMain.cs +++ b/src/csharp/Grpc.Examples.Tests/NUnitMain.cs @@ -33,7 +33,7 @@ namespace Grpc.Examples.Tests public static int Main(string[] args) { // Make logger immune to NUnit capturing stdout and stderr to workaround https://github.com/nunit/nunit/issues/1406. - GrpcEnvironment.SetLogger(new TextWriterLogger(Console.Error)); + GrpcEnvironment.SetLogger(new ConsoleLogger()); #if NETCOREAPP1_0 return new AutoRun(typeof(NUnitMain).GetTypeInfo().Assembly).Execute(args, new ExtendedTextWrapper(Console.Out), Console.In); #else diff --git a/src/csharp/Grpc.HealthCheck.Tests/NUnitMain.cs b/src/csharp/Grpc.HealthCheck.Tests/NUnitMain.cs index 57deb3ba30..365551e895 100644 --- a/src/csharp/Grpc.HealthCheck.Tests/NUnitMain.cs +++ b/src/csharp/Grpc.HealthCheck.Tests/NUnitMain.cs @@ -33,7 +33,7 @@ namespace Grpc.HealthCheck.Tests public static int Main(string[] args) { // Make logger immune to NUnit capturing stdout and stderr to workaround https://github.com/nunit/nunit/issues/1406. - GrpcEnvironment.SetLogger(new TextWriterLogger(Console.Error)); + GrpcEnvironment.SetLogger(new ConsoleLogger()); #if NETCOREAPP1_0 return new AutoRun(typeof(NUnitMain).GetTypeInfo().Assembly).Execute(args, new ExtendedTextWrapper(Console.Out), Console.In); #else diff --git a/src/csharp/Grpc.IntegrationTesting/NUnitMain.cs b/src/csharp/Grpc.IntegrationTesting/NUnitMain.cs index a36802af55..9d24762e0a 100644 --- a/src/csharp/Grpc.IntegrationTesting/NUnitMain.cs +++ b/src/csharp/Grpc.IntegrationTesting/NUnitMain.cs @@ -33,7 +33,7 @@ namespace Grpc.IntegrationTesting public static int Main(string[] args) { // Make logger immune to NUnit capturing stdout and stderr to workaround https://github.com/nunit/nunit/issues/1406. - GrpcEnvironment.SetLogger(new TextWriterLogger(Console.Error)); + GrpcEnvironment.SetLogger(new ConsoleLogger()); #if NETCOREAPP1_0 return new AutoRun(typeof(NUnitMain).GetTypeInfo().Assembly).Execute(args, new ExtendedTextWrapper(Console.Out), Console.In); #else diff --git a/src/csharp/Grpc.Microbenchmarks/Program.cs b/src/csharp/Grpc.Microbenchmarks/Program.cs index 8412ba3245..d07d4187c4 100644 --- a/src/csharp/Grpc.Microbenchmarks/Program.cs +++ b/src/csharp/Grpc.Microbenchmarks/Program.cs @@ -27,7 +27,7 @@ namespace Grpc.Microbenchmarks { public static void Main(string[] args) { - GrpcEnvironment.SetLogger(new TextWriterLogger(Console.Error)); + GrpcEnvironment.SetLogger(new ConsoleLogger()); var benchmark = new SendMessageBenchmark(); benchmark.Init(); foreach (int threadCount in new int[] {1, 1, 2, 4, 8, 12}) diff --git a/src/csharp/Grpc.Reflection.Tests/NUnitMain.cs b/src/csharp/Grpc.Reflection.Tests/NUnitMain.cs index a45dab8772..49ed1cc8d4 100644 --- a/src/csharp/Grpc.Reflection.Tests/NUnitMain.cs +++ b/src/csharp/Grpc.Reflection.Tests/NUnitMain.cs @@ -33,7 +33,7 @@ namespace Grpc.Reflection.Tests public static int Main(string[] args) { // Make logger immune to NUnit capturing stdout and stderr to workaround https://github.com/nunit/nunit/issues/1406. - GrpcEnvironment.SetLogger(new TextWriterLogger(Console.Error)); + GrpcEnvironment.SetLogger(new ConsoleLogger()); #if NETCOREAPP1_0 return new AutoRun(typeof(NUnitMain).GetTypeInfo().Assembly).Execute(args, new ExtendedTextWrapper(Console.Out), Console.In); #else diff --git a/src/csharp/build_packages_dotnetcli.bat b/src/csharp/build_packages_dotnetcli.bat index 4e3870d71d..c419d87049 100755 --- a/src/csharp/build_packages_dotnetcli.bat +++ b/src/csharp/build_packages_dotnetcli.bat @@ -13,7 +13,7 @@ @rem limitations under the License. @rem Current package versions -set VERSION=1.5.0-dev +set VERSION=1.7.0-dev @rem Adjust the location of nuget.exe set NUGET=C:\nuget\nuget.exe diff --git a/src/csharp/build_packages_dotnetcli.sh b/src/csharp/build_packages_dotnetcli.sh index f259cdb1d5..124dfbb257 100755 --- a/src/csharp/build_packages_dotnetcli.sh +++ b/src/csharp/build_packages_dotnetcli.sh @@ -39,7 +39,7 @@ dotnet pack --configuration Release Grpc.Auth --output ../../../artifacts dotnet pack --configuration Release Grpc.HealthCheck --output ../../../artifacts dotnet pack --configuration Release Grpc.Reflection --output ../../../artifacts -nuget pack Grpc.nuspec -Version "1.5.0-dev" -OutputDirectory ../../artifacts -nuget pack Grpc.Tools.nuspec -Version "1.5.0-dev" -OutputDirectory ../../artifacts +nuget pack Grpc.nuspec -Version "1.7.0-dev" -OutputDirectory ../../artifacts +nuget pack Grpc.Tools.nuspec -Version "1.7.0-dev" -OutputDirectory ../../artifacts (cd ../../artifacts && zip csharp_nugets_dotnetcli.zip *.nupkg) |