mirror of
https://github.com/Readarr/Readarr
synced 2026-01-15 12:03:17 +01:00
More mono cleanup
This commit is contained in:
parent
35ab21ab04
commit
1e0e8adc77
9 changed files with 4 additions and 438 deletions
|
|
@ -35,19 +35,10 @@ public HttpResponse GetResponse(HttpRequest request, CookieContainer cookies)
|
|||
{
|
||||
var webRequest = (HttpWebRequest)WebRequest.Create((Uri)request.Url);
|
||||
|
||||
if (PlatformInfo.IsMono && request.ResponseStream == null)
|
||||
{
|
||||
// On Mono GZipStream/DeflateStream leaks memory if an exception is thrown, use an intermediate buffer in that case.
|
||||
webRequest.AutomaticDecompression = DecompressionMethods.None;
|
||||
webRequest.Headers.Add("Accept-Encoding", "gzip");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Deflate is not a standard and could break depending on implementation.
|
||||
// we should just stick with the more compatible Gzip
|
||||
//http://stackoverflow.com/questions/8490718/how-to-decompress-stream-deflated-with-java-util-zip-deflater-in-net
|
||||
webRequest.AutomaticDecompression = DecompressionMethods.GZip;
|
||||
}
|
||||
// Deflate is not a standard and could break depending on implementation.
|
||||
// we should just stick with the more compatible Gzip
|
||||
//http://stackoverflow.com/questions/8490718/how-to-decompress-stream-deflated-with-java-util-zip-deflater-in-net
|
||||
webRequest.AutomaticDecompression = DecompressionMethods.GZip;
|
||||
|
||||
webRequest.Method = request.Method.ToString();
|
||||
webRequest.UserAgent = _userAgentBuilder.GetUserAgent(request.UseSimplifiedUserAgent);
|
||||
|
|
@ -104,9 +95,6 @@ public HttpResponse GetResponse(HttpRequest request, CookieContainer cookies)
|
|||
|
||||
if (httpWebResponse == null)
|
||||
{
|
||||
// Workaround for mono not closing connections properly in certain situations.
|
||||
AbortWebRequest(webRequest);
|
||||
|
||||
// The default messages for WebException on mono are pretty horrible.
|
||||
if (e.Status == WebExceptionStatus.NameResolutionFailure)
|
||||
{
|
||||
|
|
@ -147,12 +135,6 @@ public HttpResponse GetResponse(HttpRequest request, CookieContainer cookies)
|
|||
else
|
||||
{
|
||||
data = responseStream.ToBytes();
|
||||
|
||||
if (PlatformInfo.IsMono && httpWebResponse.ContentEncoding == "gzip")
|
||||
{
|
||||
data = data.Decompress();
|
||||
httpWebResponse.Headers.Remove("Content-Encoding");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
@ -262,37 +244,5 @@ protected virtual void AddRequestHeaders(HttpWebRequest webRequest, HttpHeader h
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Workaround for mono not closing connections properly on timeouts
|
||||
private void AbortWebRequest(HttpWebRequest webRequest)
|
||||
{
|
||||
// First affected version was mono 5.16
|
||||
if (OsInfo.IsNotWindows && _platformInfo.Version >= new Version(5, 16))
|
||||
{
|
||||
try
|
||||
{
|
||||
var currentOperationInfo = webRequest.GetType().GetField("currentOperation", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
var currentOperation = currentOperationInfo.GetValue(webRequest);
|
||||
|
||||
if (currentOperation != null)
|
||||
{
|
||||
var responseStreamInfo = currentOperation.GetType().GetField("responseStream", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
var responseStream = responseStreamInfo.GetValue(currentOperation) as Stream;
|
||||
|
||||
// Note that responseStream will likely be null once mono fixes it.
|
||||
responseStream?.Dispose();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// This can fail randomly on future mono versions that have been changed/fixed. Log to sentry and ignore.
|
||||
_logger.Trace()
|
||||
.Exception(ex)
|
||||
.Message("Unable to dispose responseStream on mono {0}", _platformInfo.Version)
|
||||
.WriteSentryWarn("MonoCloseWaitPatchFailed", ex.Message)
|
||||
.Write();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,20 +0,0 @@
|
|||
using System;
|
||||
using System.Net;
|
||||
|
||||
namespace NzbDrone.Common.Http
|
||||
{
|
||||
public class NzbDroneWebClient : WebClient
|
||||
{
|
||||
protected override WebRequest GetWebRequest(Uri address)
|
||||
{
|
||||
var request = base.GetWebRequest(address);
|
||||
if (request is HttpWebRequest)
|
||||
{
|
||||
((HttpWebRequest)request).KeepAlive = false;
|
||||
((HttpWebRequest)request).ServicePoint.Expect100Continue = false;
|
||||
}
|
||||
|
||||
return request;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
using NUnit.Framework;
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
using NzbDrone.Core.HealthCheck.Checks;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Test.Common;
|
||||
using static NzbDrone.Core.HealthCheck.Checks.MonoDebugCheck;
|
||||
|
||||
namespace NzbDrone.Core.Test.HealthCheck.Checks
|
||||
{
|
||||
[TestFixture]
|
||||
public class MonoDebugCheckFixture : CoreTest<MonoDebugCheck>
|
||||
{
|
||||
private void GivenHasStackFrame(bool hasStackFrame)
|
||||
{
|
||||
Mocker.GetMock<StackFrameHelper>()
|
||||
.Setup(f => f.HasStackFrameInfo())
|
||||
.Returns(hasStackFrame);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_ok_if_not_mono()
|
||||
{
|
||||
if (PlatformInfo.IsMono)
|
||||
{
|
||||
throw new IgnoreException("non mono specific test");
|
||||
}
|
||||
|
||||
Subject.Check().ShouldBeOk();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_ok_if_not_debug()
|
||||
{
|
||||
MonoOnly();
|
||||
|
||||
GivenHasStackFrame(false);
|
||||
|
||||
Subject.Check().ShouldBeOk();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_log_warning_if_not_debug()
|
||||
{
|
||||
MonoOnly();
|
||||
|
||||
GivenHasStackFrame(false);
|
||||
|
||||
Subject.Check();
|
||||
|
||||
ExceptionVerification.ExpectedWarns(1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_ok_if_debug()
|
||||
{
|
||||
MonoOnly();
|
||||
|
||||
GivenHasStackFrame(true);
|
||||
|
||||
Subject.Check().ShouldBeOk();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Processes;
|
||||
using NzbDrone.Core.HealthCheck.Checks;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Test.HealthCheck.Checks
|
||||
{
|
||||
[TestFixture]
|
||||
public class MonoNotNetCoreCheckFixture : CoreTest<MonoNotNetCoreCheck>
|
||||
{
|
||||
[Test]
|
||||
[Platform(Exclude = "Mono")]
|
||||
public void should_return_ok_if_net_core()
|
||||
{
|
||||
Subject.Check().ShouldBeOk();
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Platform("Mono")]
|
||||
public void should_log_warning_if_mono()
|
||||
{
|
||||
Subject.Check().ShouldBeWarning();
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Platform("Mono")]
|
||||
public void should_return_ok_if_bsd()
|
||||
{
|
||||
Mocker.GetMock<IProcessProvider>()
|
||||
.Setup(x => x.StartAndCapture("uname", null, null))
|
||||
.Returns(new ProcessOutput
|
||||
{
|
||||
Lines = new List<ProcessOutputLine>
|
||||
{
|
||||
new ProcessOutputLine(ProcessOutputLevel.Standard, "FreeBSD")
|
||||
}
|
||||
});
|
||||
Subject.Check().ShouldBeOk();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
using System;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
using NzbDrone.Core.HealthCheck.Checks;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Test.HealthCheck.Checks
|
||||
{
|
||||
[TestFixture]
|
||||
public class MonoVersionCheckFixture : CoreTest<MonoVersionCheck>
|
||||
{
|
||||
private void GivenOutput(string version)
|
||||
{
|
||||
MonoOnly();
|
||||
|
||||
Mocker.GetMock<IPlatformInfo>()
|
||||
.SetupGet(s => s.Version)
|
||||
.Returns(new Version(version));
|
||||
}
|
||||
|
||||
[TestCase("5.20")]
|
||||
public void should_return_ok(string version)
|
||||
{
|
||||
GivenOutput(version);
|
||||
|
||||
Subject.Check().ShouldBeOk();
|
||||
}
|
||||
|
||||
public void should_return_notice(string version)
|
||||
{
|
||||
GivenOutput(version);
|
||||
|
||||
Subject.Check().ShouldBeNotice();
|
||||
}
|
||||
|
||||
public void should_return_warning(string version)
|
||||
{
|
||||
GivenOutput(version);
|
||||
|
||||
Subject.Check().ShouldBeWarning();
|
||||
}
|
||||
|
||||
[TestCase("2.10.2")]
|
||||
[TestCase("2.10.8.1")]
|
||||
[TestCase("3.0.0.1")]
|
||||
[TestCase("3.2.0.1")]
|
||||
[TestCase("3.2.1")]
|
||||
[TestCase("3.2.7")]
|
||||
[TestCase("3.6.1")]
|
||||
[TestCase("3.8")]
|
||||
[TestCase("3.10")]
|
||||
[TestCase("4.0.0.0")]
|
||||
[TestCase("4.2")]
|
||||
[TestCase("4.4.0")]
|
||||
[TestCase("4.4.1")]
|
||||
[TestCase("4.6.2")]
|
||||
[TestCase("5.4")]
|
||||
[TestCase("5.8")]
|
||||
[TestCase("5.16")]
|
||||
[TestCase("5.18")]
|
||||
public void should_return_error(string version)
|
||||
{
|
||||
GivenOutput(version);
|
||||
|
||||
Subject.Check().ShouldBeError();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
using System.Diagnostics;
|
||||
using NLog;
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
using NzbDrone.Common.Extensions;
|
||||
|
||||
namespace NzbDrone.Core.HealthCheck.Checks
|
||||
{
|
||||
public class MonoDebugCheck : HealthCheckBase
|
||||
{
|
||||
private readonly Logger _logger;
|
||||
private readonly StackFrameHelper _stackFrameHelper;
|
||||
|
||||
public override bool CheckOnSchedule => false;
|
||||
|
||||
public MonoDebugCheck(Logger logger, StackFrameHelper stackFrameHelper)
|
||||
{
|
||||
_logger = logger;
|
||||
_stackFrameHelper = stackFrameHelper;
|
||||
}
|
||||
|
||||
public class StackFrameHelper
|
||||
{
|
||||
public virtual bool HasStackFrameInfo()
|
||||
{
|
||||
var stackTrace = new StackTrace(true);
|
||||
|
||||
return stackTrace.FrameCount > 0 && stackTrace.GetFrame(0).GetFileName().IsNotNullOrWhiteSpace();
|
||||
}
|
||||
}
|
||||
|
||||
public override HealthCheck Check()
|
||||
{
|
||||
if (!PlatformInfo.IsMono)
|
||||
{
|
||||
return new HealthCheck(GetType());
|
||||
}
|
||||
|
||||
if (!_stackFrameHelper.HasStackFrameInfo())
|
||||
{
|
||||
_logger.Warn("Mono is not running with --debug switch");
|
||||
return new HealthCheck(GetType());
|
||||
}
|
||||
|
||||
return new HealthCheck(GetType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using NLog;
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
using NzbDrone.Common.Processes;
|
||||
|
||||
namespace NzbDrone.Core.HealthCheck.Checks
|
||||
{
|
||||
public class MonoNotNetCoreCheck : HealthCheckBase
|
||||
{
|
||||
private static string[] MonoUnames = new string[] { "FreeBSD", "OpenBSD", "MidnightBSD", "NetBSD" };
|
||||
private readonly IOsInfo _osInfo;
|
||||
private readonly IProcessProvider _processProvider;
|
||||
|
||||
public MonoNotNetCoreCheck(IOsInfo osInfo,
|
||||
IProcessProvider processProvider,
|
||||
Logger logger)
|
||||
{
|
||||
_osInfo = osInfo;
|
||||
_processProvider = processProvider;
|
||||
}
|
||||
|
||||
public override HealthCheck Check()
|
||||
{
|
||||
if (!PlatformInfo.IsMono)
|
||||
{
|
||||
return new HealthCheck(GetType());
|
||||
}
|
||||
|
||||
// Don't warn on arm based synology - could be arm5 or something else rubbish
|
||||
if (_osInfo.Name == "DSM" && RuntimeInformation.ProcessArchitecture == Architecture.Arm)
|
||||
{
|
||||
return new HealthCheck(GetType());
|
||||
}
|
||||
|
||||
// Don't warn on linux x86 - we don't build x86 net core
|
||||
if (OsInfo.IsLinux && RuntimeInformation.ProcessArchitecture == Architecture.X86)
|
||||
{
|
||||
return new HealthCheck(GetType());
|
||||
}
|
||||
|
||||
// Check for BSD
|
||||
var output = _processProvider.StartAndCapture("uname");
|
||||
if (output?.ExitCode == 0 && MonoUnames.Contains(output?.Lines.First().Content))
|
||||
{
|
||||
return new HealthCheck(GetType());
|
||||
}
|
||||
|
||||
return new HealthCheck(GetType(),
|
||||
HealthCheckResult.Warning,
|
||||
"Please upgrade to the .NET Core version of Readarr",
|
||||
"#update-to-net-core-version");
|
||||
}
|
||||
|
||||
public override bool CheckOnSchedule => false;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
using System;
|
||||
using NLog;
|
||||
using NLog.Fluent;
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
using NzbDrone.Common.Instrumentation.Extensions;
|
||||
|
||||
namespace NzbDrone.Core.HealthCheck.Checks
|
||||
{
|
||||
public class MonoTlsCheck : HealthCheckBase
|
||||
{
|
||||
private readonly IPlatformInfo _platformInfo;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public MonoTlsCheck(IPlatformInfo platformInfo, Logger logger)
|
||||
{
|
||||
_platformInfo = platformInfo;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public override HealthCheck Check()
|
||||
{
|
||||
if (!PlatformInfo.IsMono)
|
||||
{
|
||||
return new HealthCheck(GetType());
|
||||
}
|
||||
|
||||
var monoVersion = _platformInfo.Version;
|
||||
|
||||
if (monoVersion >= new Version("5.8.0") && Environment.GetEnvironmentVariable("MONO_TLS_PROVIDER") == "legacy")
|
||||
{
|
||||
_logger.Debug()
|
||||
.Message("Mono version {0} and legacy TLS provider is selected, recommending user to switch to btls.", monoVersion)
|
||||
.WriteSentryDebug("LegacyTlsProvider", monoVersion.ToString())
|
||||
.Write();
|
||||
|
||||
return new HealthCheck(GetType(), HealthCheckResult.Warning, "Readarr Mono 4.x tls workaround still enabled, consider removing MONO_TLS_PROVIDER=legacy environment option");
|
||||
}
|
||||
|
||||
return new HealthCheck(GetType());
|
||||
}
|
||||
|
||||
public override bool CheckOnSchedule => false;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
using System;
|
||||
using NLog;
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
|
||||
namespace NzbDrone.Core.HealthCheck.Checks
|
||||
{
|
||||
public class MonoVersionCheck : HealthCheckBase
|
||||
{
|
||||
private readonly IPlatformInfo _platformInfo;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public MonoVersionCheck(IPlatformInfo platformInfo, Logger logger)
|
||||
{
|
||||
_platformInfo = platformInfo;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public override HealthCheck Check()
|
||||
{
|
||||
if (!PlatformInfo.IsMono)
|
||||
{
|
||||
return new HealthCheck(GetType());
|
||||
}
|
||||
|
||||
var monoVersion = _platformInfo.Version;
|
||||
|
||||
// Currently best stable Mono version (5.18 gets us .net 4.7.2 support)
|
||||
var bestVersion = new Version("5.20");
|
||||
if (monoVersion >= bestVersion)
|
||||
{
|
||||
_logger.Debug("Mono version is {0} or better: {1}", bestVersion, monoVersion);
|
||||
return new HealthCheck(GetType());
|
||||
}
|
||||
|
||||
return new HealthCheck(GetType(),
|
||||
HealthCheckResult.Error,
|
||||
$"Currently installed Mono version {monoVersion} is old and unsupported. Please upgrade Mono to version {bestVersion}.",
|
||||
"#currently_installed_mono_version_is_old_and_unsupported");
|
||||
}
|
||||
|
||||
public override bool CheckOnSchedule => false;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue