From 034cf66dfeef65afec5837037de2dd177ca8ce4d Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Sun, 28 Apr 2024 10:58:27 +0100 Subject: [PATCH] replace beginaccept --- OpenSim/Framework/ExpiringCacheOS.cs | 54 +++++++++++ .../OSHttpServer/ContextTimeoutManager.cs | 2 +- .../HttpServer/OSHttpServer/HttpListener.cs | 97 ++++++++----------- 3 files changed, 94 insertions(+), 59 deletions(-) diff --git a/OpenSim/Framework/ExpiringCacheOS.cs b/OpenSim/Framework/ExpiringCacheOS.cs index 00be73d110..6f6de40b7a 100644 --- a/OpenSim/Framework/ExpiringCacheOS.cs +++ b/OpenSim/Framework/ExpiringCacheOS.cs @@ -30,6 +30,7 @@ using System; using System.Threading; using System.Collections.Generic; using Timer = System.Threading.Timer; +using System.Runtime.InteropServices; namespace OpenSim.Framework { @@ -460,6 +461,59 @@ namespace OpenSim.Framework return success; } + public ref TValue1 TryGetOrDefaultValue(TKey1 key, out bool existed) + { + bool gotLock = false; + try + { + try { } + finally + { + m_rwLock.ExitUpgradeableReadLock(); + gotLock = true; + } + + return ref CollectionsMarshal.GetValueRefOrAddDefault(m_values, key, out existed); + } + finally + { + if (gotLock) + m_rwLock.ExitUpgradeableReadLock(); + } + } + + public ref TValue1 TryGetOrDefaultValue(TKey1 key, int expireMS, out bool existed) + { + bool gotLock = false; + try + { + try { } + finally + { + m_rwLock.EnterWriteLock(); + gotLock = true; + } + + ref TValue1 ret = ref CollectionsMarshal.GetValueRefOrAddDefault(m_values, key, out existed); + int now; + if (expireMS > 0) + { + expireMS = (expireMS > m_expire) ? expireMS : m_expire; + now = (int)(Util.GetTimeStampMS() - m_startTS) + expireMS; + } + else + now = int.MinValue; + + m_expireControl[key] = now; + return ref ret; + } + finally + { + if (gotLock) + m_rwLock.EnterWriteLock(); + } + } + public TValue1[] Values { get diff --git a/OpenSim/Framework/Servers/HttpServer/OSHttpServer/ContextTimeoutManager.cs b/OpenSim/Framework/Servers/HttpServer/OSHttpServer/ContextTimeoutManager.cs index dbf0c2d596..bebe2fbb48 100644 --- a/OpenSim/Framework/Servers/HttpServer/OSHttpServer/ContextTimeoutManager.cs +++ b/OpenSim/Framework/Servers/HttpServer/OSHttpServer/ContextTimeoutManager.cs @@ -322,7 +322,7 @@ namespace OSHttpServer default: return; } - m_processWaitEven.Set(); + m_processWaitEven?.Set(); } public static void PulseWaitSend() diff --git a/OpenSim/Framework/Servers/HttpServer/OSHttpServer/HttpListener.cs b/OpenSim/Framework/Servers/HttpServer/OSHttpServer/HttpListener.cs index af9f9ea622..4be06324c1 100644 --- a/OpenSim/Framework/Servers/HttpServer/OSHttpServer/HttpListener.cs +++ b/OpenSim/Framework/Servers/HttpServer/OSHttpServer/HttpListener.cs @@ -5,6 +5,8 @@ using System.Net.Security; using System.Security.Authentication; using System.Security.Cryptography.X509Certificates; using System.Threading; +using System.Threading.Tasks; +using System.Runtime.CompilerServices; namespace OSHttpServer { @@ -19,8 +21,8 @@ namespace OSHttpServer private TcpListener m_listener; private ILogWriter m_logWriter = NullLogWriter.Instance; - private int m_pendingAccepts; private bool m_shutdown; + public readonly CancellationTokenSource m_CancellationSource = new(); protected RemoteCertificateValidationCallback m_clientCertValCallback = null; public event EventHandler Accepted; @@ -86,6 +88,7 @@ namespace OSHttpServer return new OSHttpListener(address, port, certificate, protocols); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] private void OnRequestReceived(object sender, RequestEventArgs e) { RequestReceived?.Invoke(sender, e); @@ -120,76 +123,53 @@ namespace OSHttpServer /// public bool UseTraceLogs { get; set; } - - /// Exception. - private void OnAccept(IAsyncResult ar) + private async void AcceptLoop() { - bool beginAcceptCalled = false; try { - int count = Interlocked.Decrement(ref m_pendingAccepts); - if (m_shutdown) + while (true) { - if (count == 0) + if (m_shutdown) + { m_shutdownEvent.Set(); - return; - } + break; + } - Interlocked.Increment(ref m_pendingAccepts); - m_listener.BeginAcceptSocket(OnAccept, null); - beginAcceptCalled = true; - Socket socket = m_listener.EndAcceptSocket(ar); - if (!socket.Connected) - { - socket.Dispose(); - return; - } + Socket socket = await m_listener.AcceptSocketAsync(m_CancellationSource.Token).ConfigureAwait(false); ; + if (!socket.Connected) + { + socket.Dispose(); + continue; + } - socket.NoDelay = true; + socket.NoDelay = true; - if (!OnAcceptingSocket(socket)) - { - socket.Disconnect(true); - return; - } + if (!OnAcceptingSocket(socket)) + { + socket.Disconnect(true); + continue; + } + if (socket.Connected) + { + m_logWriter.Write(this, LogPrio.Debug, $"Accepted connection from: {socket.RemoteEndPoint}"); - if(socket.Connected) - { - m_logWriter.Write(this, LogPrio.Debug, $"Accepted connection from: {socket.RemoteEndPoint}"); - - if (m_certificate is not null) - m_contextFactory.CreateSecureContext(socket, m_certificate, m_sslProtocols, m_clientCertValCallback); + if (m_certificate is not null) + m_contextFactory.CreateSecureContext(socket, m_certificate, m_sslProtocols, m_clientCertValCallback); + else + m_contextFactory.CreateContext(socket); + } else - m_contextFactory.CreateContext(socket); + socket.Dispose(); } - else - socket.Dispose(); + } + catch (OperationCanceledException) + { + m_shutdownEvent.Set(); } catch (Exception err) { m_logWriter.Write(this, LogPrio.Debug, err.Message); ExceptionThrown?.Invoke(this, err); - - if (!beginAcceptCalled) - RetryBeginAccept(); - } - } - - /// - /// Will try to accept connections one more time. - /// - /// If any exceptions is thrown. - private void RetryBeginAccept() - { - try - { - m_logWriter.Write(this, LogPrio.Error, "Trying to accept connections again."); - m_listener.BeginAcceptSocket(OnAccept, null); - } - catch (Exception err) - { - m_logWriter.Write(this, LogPrio.Fatal, err.Message); - ExceptionThrown?.Invoke(this, err); } } @@ -221,8 +201,7 @@ namespace OSHttpServer m_listener = new TcpListener(m_address, m_port); m_listener.Start(backlog); - Interlocked.Increment(ref m_pendingAccepts); - m_listener.BeginAcceptSocket(OnAccept, null); + Task.Run(AcceptLoop).ConfigureAwait(false); } /// @@ -232,10 +211,11 @@ namespace OSHttpServer public void Stop() { m_shutdown = true; + m_CancellationSource.Cancel(); m_contextFactory.Shutdown(); - m_listener.Stop(); if (!m_shutdownEvent.WaitOne()) m_logWriter.Write(this, LogPrio.Error, "Failed to shutdown listener properly."); + m_listener.Stop(); m_listener = null; Dispose(); } @@ -251,6 +231,7 @@ namespace OSHttpServer if (m_shutdownEvent != null) { m_shutdownEvent.Dispose(); + m_CancellationSource.Dispose(); } } }