Удаленное продление аренды иногда не удается - PullRequest
0 голосов
/ 08 сентября 2018

У меня есть настольное приложение Windows, написанное на C # .NET, которое должно компилировать и запускать частично доверенный код.Я обрабатываю это как плагин: скомпилируйте код в .DLL, затем загрузите сборку и выполните ее в AppDomain.AppDomain довольно ограничен, имеет только разрешения на выполнение, инфраструктуру и RemotingConfiguration, а также возможность чтения файлов из каталога, в котором находятся библиотеки DLL.

Во время работы в отладчике (Visual Studio Community 2017), удаленномсторона иногда не может возобновить аренду.Затем удаленный объект «Диспетчер плагинов» получает GCed, и следующая попытка основного приложения взаимодействовать с плагином завершается неудачей с RemotingException.

. Поведение очень противоречиво.В большинстве случаев все работает нормально, но иногда это не помогает.Это часто терпит неудачу прежде, чем арендный договор продлевается впервые, но иногда это терпит неудачу после нескольких продлений.Единственная подсказка, которую я имею сейчас, - это сообщение, напечатанное на консоли отладчика:

Exception thrown: 'System.Runtime.Remoting.RemotingException' in mscorlib.dll
Exception thrown: 'System.Runtime.Remoting.RemotingException' in mscorlib.dll

Через некоторое время после их появления объект «Менеджер плагинов» получает GCed (я добавил деструктор, который пишет сообщение вприставка).Таким образом, кажется, что попытка удаленного пользователя продлить аренду не удалась, и объект был собран.

Почему это происходит?Что я могу сделать, чтобы предотвратить это?

У меня есть сообщения журнала в объекте спонсора, которые показывают главное приложение, возобновляющее аренду.Они выглядят так:

15:17:20|Lease renewal for PluginCommon.PluginManager, last renewed 00:05:00.1248814 sec ago; renewing for 00:02:00 (host id=1)
15:19:20|Lease renewal for PluginCommon.PluginManager, last renewed 00:02:00.0281627 sec ago; renewing for 00:02:00 (host id=1)

Это ожидаемое поведение, когда мое приложение бездействует - первоначально 5 минут, обновляйте каждые 2. Первоначальная пятиминутная задержка делает отладку несколько неприятной.

Заметьте, я не могу переопределить InitializeLifetimeService(), не сделав разрешения безопасности, поэтому я не могу просто заставить объект жить вечно (что было бы приемлемым решением здесь).Я пытался провести несколько экспериментов с разрешающей безопасностью и 10-секундными таймаутами, но пока не видел, как он потерпел неудачу (что, учитывая спорадическую природу сбоев, не обязательно что-то значит).

Мой класс Спонсорапримерно то, что вы ожидаете:

class Sponsor<T> : MarshalByRefObject, ISponsor, IDisposable where T : MarshalByRefObject

Домен приложения "плагин" создается следующим образом:

        PluginManager pm = (PluginManager)mAppDomain.CreateInstanceAndUnwrap(
            typeof(PluginManager).Assembly.FullName,
            typeof(PluginManager).FullName);

        // Wrap it so it doesn't disappear on us.
        mPluginManager = new Sponsor<PluginManager>(pm);

Спонсируемый объект PluginManager является единственной связью между основным доменом приложения иПлагин AppDomain.


При наборе этого текста, приложение зависало, не создавая аренду.Я добавил RemotingException в список прерываний исключений, который привел к следующей трассировке стека:

mscorlib.dll!System.Runtime.Remoting.Channels.ChannelServices.CheckDisconnectedOrCreateWellKnownObject(System.Runtime.Remoting.Messaging.IMessage msg)  Unknown
mscorlib.dll!System.Runtime.Remoting.Channels.ChannelServices.SyncDispatchMessage(System.Runtime.Remoting.Messaging.IMessage msg)   Unknown
mscorlib.dll!System.Runtime.Remoting.Channels.CrossAppDomainSink.DoDispatch(byte[] reqStmBuff, System.Runtime.Remoting.Messaging.SmuggledMethodCallMessage smuggledMcm, out System.Runtime.Remoting.Messaging.SmuggledMethodReturnMessage smuggledMrm)  Unknown
mscorlib.dll!System.Runtime.Remoting.Channels.CrossAppDomainSink.DoTransitionDispatchCallback(object[] args)    Unknown
mscorlib.dll!System.Threading.Thread.CompleteCrossContextCallback(System.Threading.InternalCrossContextDelegate ftnToCall, object[] args)   Unknown
[AppDomain (Plugin Domain, #2) -> AppDomain (SourceGen.exe, #1)]    
mscorlib.dll!System.Runtime.Remoting.Channels.CrossAppDomainSink.DoTransitionDispatch(byte[] reqStmBuff, System.Runtime.Remoting.Messaging.SmuggledMethodCallMessage smuggledMcm, out System.Runtime.Remoting.Messaging.SmuggledMethodReturnMessage smuggledMrm)    Unknown
mscorlib.dll!System.Runtime.Remoting.Channels.CrossAppDomainSink.SyncProcessMessage(System.Runtime.Remoting.Messaging.IMessage reqMsg)  Unknown
mscorlib.dll!System.Runtime.Remoting.Channels.ADAsyncWorkItem.FinishAsyncWork(object stateIgnored)  Unknown
mscorlib.dll!System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(object state)  Unknown
mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx)   Unknown
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx)   Unknown
mscorlib.dll!System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()  Unknown
mscorlib.dll!System.Threading.ThreadPoolWorkQueue.Dispatch()    Unknown
mscorlib.dll!System.Threading._ThreadPoolWaitCallback.PerformWaitCallback() Unknown
[Native to Managed Transition]  

Я не уверен, какие обходные пути доступны - возможно, System.Timers.Timer проверяет его каждые 60 секундбудет поддерживать жизнь, даже если домен плагина не сможет связаться с основным приложением?

Есть похожие вопросы по SO (например, this ), но они описывают последовательно воспроизводимое поведение.

Обновление: FWIW, 60-секундный пинг-клюж, кажется, работает.Механизм продления по вызову сохраняет объект в разогретом состоянии, поэтому ему не нужно запрашивать продление аренды.

...