aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Engelbrecht <[email protected]>2022-12-07 14:24:13 +0100
committerGitHub <[email protected]>2022-12-07 05:24:13 -0800
commitde76241479f30ab52298de47439c7268dd45391e (patch)
tree7e8f5040cce7d438fa60d5b6bc56d0cfb31eb053
parent0.2.0-pre0 (diff)
downloadzen-de76241479f30ab52298de47439c7268dd45391e.tar.xz
zen-de76241479f30ab52298de47439c7268dd45391e.zip
Fix asio port sharing options (#203)
* Windows: explicitly set the special SO_EXCLUSIVEADDRUSE flag * changelog
-rw-r--r--CHANGELOG.md11
-rw-r--r--zenhttp/httpasio.cpp30
2 files changed, 32 insertions, 9 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f8bcd92fa..22f71bb56 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,17 +1,18 @@
##
-- Feature: Recording and playback of cache request with full data - both get and put operations can be replayed. Invoke via web request.
+- Feature: Recording and playback of cache request with full data - both get and put operations can be replayed. Invoke via web request
- `<host>/z$/exec$/start-recording?<disk-storage-path>`
- `<host>/z$/exec$/stop-recording`
- `<host>/z$/exec$/replay-recording?<thread-count>&<disk-storage-path>`
-- Feature: Disk size triggered GC, a soft disk usage limit for cache data.
-- Feature: New option `--gc-disk-size-soft-limit` (command line), `gc.cache.disksizesoftlimit` (lua config) controlling limit for soft disk usage limit. Defaults to zero which disables soft disk usage limit.
-- Improvement: Disk write pressure in GC log and cleaned up clutter in GC logging.
-- Improvement: Much improved performance, between 2x to 9x improvement under heavy load (excluding http service overhead). See https://github.com/EpicGames/zen/pull/200 for details.
+- Feature: Disk size triggered GC, a soft disk usage limit for cache data
+- Feature: New option `--gc-disk-size-soft-limit` (command line), `gc.cache.disksizesoftlimit` (lua config) controlling limit for soft disk usage limit. Defaults to zero which disables soft disk usage limit
+- Improvement: Disk write pressure in GC log and cleaned up clutter in GC logging
+- Improvement: Much improved performance, between 2x to 9x improvement under heavy load (excluding http service overhead). See https://github.com/EpicGames/zen/pull/200 for details
- Bugfix: Always store records or oplog entries before storing attachments to avoid GC finding unreferenced chunks i CidStore
- Bugfix: Updated Zen `drop` command to support namespaces
- Bugfix: Use ZEN_CONSOLE for output to console in Zen commands
- Bugfix: Zen `status` command now shows info about found Zen instances
- Bugfix: Zen `top` command now shows session id string
+- Bugfix: On Windows platforms explicitly set the special `SO_EXCLUSIVEADDRUSE` flag as `SO_REUSEADDR` still allows shared use of sockets
- Changed: Reduced GC `INFO` spam by converting to `DEBUG` log messages
- Changed: Use Iso8601 format for logging start and end message
diff --git a/zenhttp/httpasio.cpp b/zenhttp/httpasio.cpp
index 39a363711..68984c86d 100644
--- a/zenhttp/httpasio.cpp
+++ b/zenhttp/httpasio.cpp
@@ -932,22 +932,42 @@ HttpRequest::OnMessageComplete()
struct HttpAcceptor
{
- HttpAcceptor(HttpAsioServerImpl& Server, asio::io_service& IoService, uint16_t Port)
+ HttpAcceptor(HttpAsioServerImpl& Server, asio::io_service& IoService, uint16_t BasePort)
: m_Server(Server)
, m_IoService(IoService)
, m_Acceptor(m_IoService, asio::ip::tcp::v6())
{
m_Acceptor.set_option(asio::ip::v6_only(false));
- m_Acceptor.set_option(asio::socket_base::reuse_address(true));
+#if ZEN_PLATFORM_WINDOWS
+ // Special option for Windows settings as !asio::socket_base::reuse_address is not the same as exclusive access on Windows platforms
+ typedef asio::detail::socket_option::boolean<ASIO_OS_DEF(SOL_SOCKET), SO_EXCLUSIVEADDRUSE> excluse_address;
+ m_Acceptor.set_option(excluse_address(true));
+#else // ZEN_PLATFORM_WINDOWS
+ m_Acceptor.set_option(asio::socket_base::reuse_address(false));
+#endif // ZEN_PLATFORM_WINDOWS
+
m_Acceptor.set_option(asio::ip::tcp::no_delay(true));
m_Acceptor.set_option(asio::socket_base::receive_buffer_size(128 * 1024));
m_Acceptor.set_option(asio::socket_base::send_buffer_size(256 * 1024));
+ uint16_t EffectivePort = BasePort;
+
asio::error_code BindErrorCode;
- m_Acceptor.bind(asio::ip::tcp::endpoint(asio::ip::address_v6::any(), Port), BindErrorCode);
+ m_Acceptor.bind(asio::ip::tcp::endpoint(asio::ip::address_v6::any(), EffectivePort), BindErrorCode);
+ // Sharing violation implies the port is being used by another process
+ for (uint16_t PortOffset = 1; (BindErrorCode == asio::error::address_in_use) && (PortOffset < 10); ++PortOffset)
+ {
+ EffectivePort = BasePort + (PortOffset * 100);
+ m_Acceptor.bind(asio::ip::tcp::endpoint(asio::ip::address_v6::any(), EffectivePort), BindErrorCode);
+ }
if (BindErrorCode == asio::error::access_denied)
{
- m_Acceptor.bind(asio::ip::tcp::endpoint(asio::ip::address_v6::any(), 0));
+ EffectivePort = 0;
+ m_Acceptor.bind(asio::ip::tcp::endpoint(asio::ip::address_v6::any(), EffectivePort), BindErrorCode);
+ }
+ if (BindErrorCode)
+ {
+ ZEN_ERROR("Unable open asio service, error '{}'", BindErrorCode.message());
}
#if ZEN_PLATFORM_WINDOWS
@@ -969,6 +989,8 @@ struct HttpAcceptor
0);
#endif
m_Acceptor.listen();
+
+ ZEN_INFO("Started asio server at port '{}'", EffectivePort);
}
void Start()