diff --git a/src/csharp/Grpc.Core.Tests/ServerTest.cs b/src/csharp/Grpc.Core.Tests/ServerTest.cs
index 3b51aa63300..5e95ed9ea61 100644
--- a/src/csharp/Grpc.Core.Tests/ServerTest.cs
+++ b/src/csharp/Grpc.Core.Tests/ServerTest.cs
@@ -32,6 +32,7 @@
#endregion
using System;
+using System.IO;
using System.Linq;
using Grpc.Core;
using Grpc.Core.Internal;
@@ -80,6 +81,21 @@ namespace Grpc.Core.Tests
server.ShutdownAsync().Wait();
}
+ [Test]
+ public void StartThrowsWithUnboundPorts()
+ {
+ int twiceBoundPort = 9999;
+ Server server = new Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) })
+ {
+ Ports = {
+ new ServerPort("localhost", twiceBoundPort, ServerCredentials.Insecure),
+ new ServerPort("localhost", twiceBoundPort, ServerCredentials.Insecure)
+ }
+ };
+ Assert.Throws(typeof(IOException), () => server.Start());
+ server.ShutdownAsync().Wait();
+ }
+
[Test]
public void CannotModifyAfterStarted()
{
diff --git a/src/csharp/Grpc.Core/Server.cs b/src/csharp/Grpc.Core/Server.cs
index 63c1d9cd00f..1fb5c62c8fb 100644
--- a/src/csharp/Grpc.Core/Server.cs
+++ b/src/csharp/Grpc.Core/Server.cs
@@ -34,6 +34,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
+using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Grpc.Core.Internal;
@@ -155,6 +156,7 @@ namespace Grpc.Core
///
/// Starts the server.
+ /// Throws IOException if not successful.
///
public void Start()
{
@@ -163,7 +165,8 @@ namespace Grpc.Core
GrpcPreconditions.CheckState(!startRequested);
GrpcPreconditions.CheckState(!shutdownRequested);
startRequested = true;
-
+
+ CheckPortsBoundSuccessfully();
handle.Start();
for (int i = 0; i < requestCallTokensPerCq; i++)
@@ -316,6 +319,22 @@ namespace Grpc.Core
}
}
+ ///
+ /// Checks that all ports have been bound successfully.
+ ///
+ private void CheckPortsBoundSuccessfully()
+ {
+ lock (myLock)
+ {
+ var unboundPort = ports.FirstOrDefault(port => port.BoundPort == 0);
+ if (unboundPort != null)
+ {
+ throw new IOException(
+ string.Format("Failed to bind port \"{0}:{1}\"", unboundPort.Host, unboundPort.Port));
+ }
+ }
+ }
+
private void DisposeHandle()
{
var activeCallCount = activeCallCounter.Count;