diff --git a/src/core/Akka.API.Tests/CoreAPISpec.ApproveCore.approved.txt b/src/core/Akka.API.Tests/CoreAPISpec.ApproveCore.approved.txt
index 13add790593..cdb9b591509 100644
--- a/src/core/Akka.API.Tests/CoreAPISpec.ApproveCore.approved.txt
+++ b/src/core/Akka.API.Tests/CoreAPISpec.ApproveCore.approved.txt
@@ -4758,6 +4758,7 @@ namespace Akka.Util
public class static RuntimeDetector
{
public static readonly bool IsMono;
+ public static readonly bool IsWindows;
}
public class static StandardOutWriter
{
diff --git a/src/core/Akka.Remote.Tests/RemoteConfigSpec.cs b/src/core/Akka.Remote.Tests/RemoteConfigSpec.cs
index 436c7b6b397..a6a088865ce 100644
--- a/src/core/Akka.Remote.Tests/RemoteConfigSpec.cs
+++ b/src/core/Akka.Remote.Tests/RemoteConfigSpec.cs
@@ -102,7 +102,7 @@ public void Remoting_should_contain_correct_heliosTCP_values_in_ReferenceConf()
Assert.Equal(4096, s.Backlog);
Assert.True(s.TcpNoDelay);
Assert.True(s.TcpKeepAlive);
- Assert.True(s.TcpReuseAddr);
+ Assert.Equal("off-for-windows", c.GetString("tcp-reuse-addr"));
Assert.True(string.IsNullOrEmpty(c.GetString("hostname")));
Assert.Null(s.PublicPort);
Assert.Equal(2, s.ServerSocketWorkerPoolSize);
diff --git a/src/core/Akka.Remote/Configuration/Remote.conf b/src/core/Akka.Remote/Configuration/Remote.conf
index e8c6255bd62..ff207b4e207 100644
--- a/src/core/Akka.Remote/Configuration/Remote.conf
+++ b/src/core/Akka.Remote/Configuration/Remote.conf
@@ -473,10 +473,10 @@ akka {
# Enables SO_REUSEADDR, which determines when an ActorSystem can open
# the specified listen port (the meaning differs between *nix and Windows)
- # Valid values are "on", "off" and "off-for-windows"
+ # Valid values are "on", "off", and "off-for-windows"
# due to the following Windows bug: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4476378
# "off-for-windows" of course means that it's "on" for all other platforms
- tcp-reuse-addr = on
+ tcp-reuse-addr = off-for-windows
# Used to configure the number of I/O worker threads on server sockets
server-socket-worker-pool {
diff --git a/src/core/Akka.Remote/Transport/DotNetty/DotNettyTransportSettings.cs b/src/core/Akka.Remote/Transport/DotNetty/DotNettyTransportSettings.cs
index 3e8420a6f8a..8aaf23b4776 100644
--- a/src/core/Akka.Remote/Transport/DotNetty/DotNettyTransportSettings.cs
+++ b/src/core/Akka.Remote/Transport/DotNetty/DotNettyTransportSettings.cs
@@ -29,6 +29,27 @@ public static DotNettyTransportSettings Create(ActorSystem system)
return Create(system.Settings.Config.GetConfig("akka.remote.dot-netty.tcp"));
}
+ ///
+ /// Adds support for the "off-for-windows" option per https://github.com/akkadotnet/akka.net/issues/3293
+ ///
+ /// The HOCON string for the akka.remote.dot-netty.tcp.reuse-addr option
+ /// true if we should enable REUSE_ADDR for tcp. false otherwise.
+ internal static bool ResolveTcpReuseAddrOption(string hoconTcpReuseAddr)
+ {
+ switch (hoconTcpReuseAddr.ToLowerInvariant())
+ {
+ case "off-for-windows" when RuntimeDetector.IsWindows:
+ return false;
+ case "off-for-windows":
+ return true;
+ case "on":
+ return true;
+ case "off":
+ default:
+ return false;
+ }
+ }
+
public static DotNettyTransportSettings Create(Config config)
{
if (config == null) throw new ArgumentNullException(nameof(config), "DotNetty HOCON config was not found (default path: `akka.remote.dot-netty`)");
@@ -61,7 +82,7 @@ public static DotNettyTransportSettings Create(Config config)
maxFrameSize: ToNullableInt(config.GetByteSize("maximum-frame-size")) ?? 128000,
ssl: config.HasPath("ssl") ? SslSettings.Create(config.GetConfig("ssl")) : SslSettings.Empty,
dnsUseIpv6: config.GetBoolean("dns-use-ipv6", false),
- tcpReuseAddr: config.GetBoolean("tcp-reuse-addr", true),
+ tcpReuseAddr: ResolveTcpReuseAddrOption(config.GetString("tcp-reuse-addr", "off-for-windows")),
tcpKeepAlive: config.GetBoolean("tcp-keepalive", true),
tcpNoDelay: config.GetBoolean("tcp-nodelay", true),
backlog: config.GetInt("backlog", 4096),
diff --git a/src/core/Akka/Util/RuntimeDetector.cs b/src/core/Akka/Util/RuntimeDetector.cs
index 2dfb06facdd..a5441b8a141 100644
--- a/src/core/Akka/Util/RuntimeDetector.cs
+++ b/src/core/Akka/Util/RuntimeDetector.cs
@@ -6,10 +6,7 @@
//-----------------------------------------------------------------------
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using System.Runtime.InteropServices;
namespace Akka.Util
{
@@ -28,6 +25,25 @@ public static class RuntimeDetector
/// Is true if we're running on a Mono VM. false otherwise.
///
public static readonly bool IsMono = Type.GetType("Mono.Runtime") != null;
+
+ ///
+ /// Is true if we've detected Windows as a platform.
+ ///
+ public static readonly bool IsWindows = _IsWindows();
+
+ ///
+ /// Private implementation method not meant for public consumption
+ ///
+ /// true if the current runtime is Windows
+ private static bool _IsWindows()
+ {
+#if CORECLR
+ return System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
+#else
+ return System.Environment.OSVersion.Platform != PlatformID.MacOSX &&
+ System.Environment.OSVersion.Platform != PlatformID.Unix;
+#endif
+ }
}
}