From 67dd5abc31f7c796d032ad9965bdac6421ffdd2e Mon Sep 17 00:00:00 2001 From: Matt Varblow Date: Tue, 15 Dec 2015 16:07:34 -0500 Subject: [PATCH 1/2] Fixes #1978: Long-running Orchard commands crashed the command line due to expired leases on remote proxies for MarshalByRef parameters passed in cross-AppDomain calls. --- src/Orchard/Localization/LocalizedString.cs | 4 ++++ src/Orchard/Logging/OrchardLog4netLogger.cs | 4 ++++ src/Tools/Orchard/Host/CommandHost.cs | 24 ++++++++++++++++++- src/Tools/Orchard/Logger.cs | 5 ++++ src/Tools/Orchard/OrchardParameters.cs | 5 ++++ .../ResponseFiles/ResponseFileReader.cs | 5 ++++ 6 files changed, 46 insertions(+), 1 deletion(-) diff --git a/src/Orchard/Localization/LocalizedString.cs b/src/Orchard/Localization/LocalizedString.cs index 2b7024416..60bddd38b 100644 --- a/src/Orchard/Localization/LocalizedString.cs +++ b/src/Orchard/Localization/LocalizedString.cs @@ -78,5 +78,9 @@ namespace Orchard.Localization { return string.Equals(_localized, that._localized); } + public override object InitializeLifetimeService() { + // never expire the cross-AppDomain lease on this object + return null; + } } } diff --git a/src/Orchard/Logging/OrchardLog4netLogger.cs b/src/Orchard/Logging/OrchardLog4netLogger.cs index 34f52d21f..2e39b8f36 100644 --- a/src/Orchard/Logging/OrchardLog4netLogger.cs +++ b/src/Orchard/Logging/OrchardLog4netLogger.cs @@ -415,5 +415,9 @@ namespace Orchard.Logging { } } + public override object InitializeLifetimeService() { + // never expire the cross-AppDomain lease on this object + return null; + } } } \ No newline at end of file diff --git a/src/Tools/Orchard/Host/CommandHost.cs b/src/Tools/Orchard/Host/CommandHost.cs index 818e8aa6a..2e17ffd7b 100644 --- a/src/Tools/Orchard/Host/CommandHost.cs +++ b/src/Tools/Orchard/Host/CommandHost.cs @@ -2,6 +2,8 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Runtime.Remoting; +using System.Runtime.Remoting.Lifetime; using System.Security; using System.Web.Hosting; using Orchard.Parameters; @@ -32,28 +34,46 @@ namespace Orchard.Host { [SecurityCritical] public override object InitializeLifetimeService() { - // never expire the license + // never expire the cross-AppDomain lease on this object return null; } + private static void ExtendLifeTimeLeases(TextReader input, TextWriter output) { + // Orchard objects passed as parameters into this AppDomain should derive from MarshalByRefObject and have + // infinite lease timeouts by means of their InitializeLifetimeService overrides. For the input/output + // stream objects we approximate that behavior by immediately renewing the lease for 30 days. + ExtendLifeTimeLease(input); + ExtendLifeTimeLease(output); + } + + private static void ExtendLifeTimeLease(MarshalByRefObject obj) { + if (RemotingServices.IsObjectOutOfAppDomain(obj)) { + var lease = (ILease)RemotingServices.GetLifetimeService(obj); + lease.Renew(TimeSpan.FromDays(30)); + } + } + [SecuritySafeCritical] void IRegisteredObject.Stop(bool immediate) { HostingEnvironment.UnregisterObject(this); } public CommandReturnCodes StartSession(TextReader input, TextWriter output) { + ExtendLifeTimeLeases(input, output); _agent = CreateAgent(); return StartHost(_agent, input, output); } public void StopSession(TextReader input, TextWriter output) { if (_agent != null) { + ExtendLifeTimeLeases(input, output); StopHost(_agent, input, output); _agent = null; } } public CommandReturnCodes RunCommand(TextReader input, TextWriter output, Logger logger, OrchardParameters args) { + ExtendLifeTimeLeases(input, output); var agent = CreateAgent(); CommandReturnCodes result = (CommandReturnCodes)agent.GetType().GetMethod("RunSingleCommand").Invoke(agent, new object[] { input, @@ -66,6 +86,7 @@ namespace Orchard.Host { } public CommandReturnCodes RunCommandInSession(TextReader input, TextWriter output, Logger logger, OrchardParameters args) { + ExtendLifeTimeLeases(input, output); CommandReturnCodes result = (CommandReturnCodes)_agent.GetType().GetMethod("RunCommand").Invoke(_agent, new object[] { input, output, @@ -77,6 +98,7 @@ namespace Orchard.Host { } public CommandReturnCodes RunCommands(TextReader input, TextWriter output, Logger logger, IEnumerable responseLines) { + ExtendLifeTimeLeases(input, output); var agent = CreateAgent(); CommandReturnCodes result = StartHost(agent, input, output); diff --git a/src/Tools/Orchard/Logger.cs b/src/Tools/Orchard/Logger.cs index 759130101..d45124b6e 100644 --- a/src/Tools/Orchard/Logger.cs +++ b/src/Tools/Orchard/Logger.cs @@ -17,5 +17,10 @@ namespace Orchard { _output.WriteLine(format, args); } } + + public override object InitializeLifetimeService() { + // never expire the cross-AppDomain lease on this object + return null; + } } } diff --git a/src/Tools/Orchard/OrchardParameters.cs b/src/Tools/Orchard/OrchardParameters.cs index 3a5d74785..130c2265b 100644 --- a/src/Tools/Orchard/OrchardParameters.cs +++ b/src/Tools/Orchard/OrchardParameters.cs @@ -10,5 +10,10 @@ namespace Orchard { public IList Arguments { get; set; } public IList ResponseFiles { get; set; } public IDictionary Switches { get; set; } + + public override object InitializeLifetimeService() { + // never expire the cross-AppDomain lease on this object + return null; + } } } \ No newline at end of file diff --git a/src/Tools/Orchard/ResponseFiles/ResponseFileReader.cs b/src/Tools/Orchard/ResponseFiles/ResponseFileReader.cs index bb6a93804..d3329ba63 100644 --- a/src/Tools/Orchard/ResponseFiles/ResponseFileReader.cs +++ b/src/Tools/Orchard/ResponseFiles/ResponseFileReader.cs @@ -10,6 +10,11 @@ namespace Orchard.ResponseFiles { public string LineText { get; set; } public int LineNumber { get; set; } public string[] Args { get; set; } + + public override object InitializeLifetimeService() { + // never expire the cross-AppDomain lease on this object + return null; + } } public class ResponseFileReader { From 4362b00da17e0244838b96f4d9ae6643d1343091 Mon Sep 17 00:00:00 2001 From: Matt Varblow Date: Tue, 15 Dec 2015 16:09:24 -0500 Subject: [PATCH 2/2] Fixed indentation --- src/Tools/Orchard/Host/CommandHost.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Tools/Orchard/Host/CommandHost.cs b/src/Tools/Orchard/Host/CommandHost.cs index 2e17ffd7b..9ef6e29d6 100644 --- a/src/Tools/Orchard/Host/CommandHost.cs +++ b/src/Tools/Orchard/Host/CommandHost.cs @@ -34,7 +34,7 @@ namespace Orchard.Host { [SecurityCritical] public override object InitializeLifetimeService() { - // never expire the cross-AppDomain lease on this object + // never expire the cross-AppDomain lease on this object return null; }