D7. Hydra Host crash

Delphi 7 host
WPF Plugin with DevExpress controls

We have found a situation which causes the Hydra host program to crash.
I have recreated this in the following test project.
Sample project

Host source included.
Plugin source can be uploaded if needed.

To recreate the crash.

  1. Open plugin instance
  2. Click a button to show either a MessageBox or a Dialog.
  3. Dismiss the popup
  4. Unload (and unload) the plugin
  5. Minimise the host to the taskbar
  6. When attempting to restore the host it crashes.

I think any operation which removes focus from the host and then attempts to restore focus causes the crash (just click on file explorer etc, then attempt to refocus the host).

I think I’ve tracked the crash down to the following source.
The Self.SetFocus is attempting to set focus to the plugin, even though it has been unloaded.
This causes a Exception “cannot focus a disabled or invisible window”

procedure THYVCLCrossPlatformPanel.WMFocusOutOfHost(var Message: 
TMessage);
begin
  if not fFocusChanging then begin
    fFocusChanging := true;
    try
      Self.SetFocus;
    finally
      fFocusChanging := false;
    end;
  end;
end;

If I don’t unload the plugin the the crash doesn’t happen. But I can’t create another instance of it. You can try this by unchecking the unload when you close in the sample host.

Thanks
Martin.

Hi,

try to use this workaround:

      LoadManagedModule('PluginModule1.dll', hcdDefaultDomain);

Hi.
I can confirm that this does solve the crash.

Could you explain briefly what this is doing please and whether there are any issues or points to watch for using hcdDefaultDomain.

Many Thanks, this was a real issue for us.
Martin

Hi,

when hcdDefaultDomain is used, it uses the default domain for the current process.
see more about this domain at https://docs.microsoft.com/en-us/dotnet/framework/unmanaged-api/hosting/icorruntimehost-getdefaultdomain-method

when you pass True/False as 2nd parameter, it used hcdNewAppDomain or hcdGlobalHydraDomain accordingly.

Hi.
Unfortunately another issue has now arisen with the main application.
Using hcdDefaultDomain causes the following exception if the plugin is Loaded / Released / Unloaded, then loaded again.

Changing to NewAppDomain we can load/reload, but the crash occurs. Nothing’s ever simple is it !

2020-06-15 14:03:33.9792|INFO|DonorManagementPlugin.PluginContainer|Starting Donor Application
2020-06-15 14:03:33.9792|INFO|DonorManagementPlugin.PluginContainer|Starting IMetricsService
2020-06-15 14:03:33.9792|INFO|DonorManagementPlugin.PluginContainer|Started IMetricsService
2020-06-15 14:03:33.9956|INFO|DonorManagementPlugin.PluginContainer|Applying theme
2020-06-15 14:03:33.9956|INFO|DonorManagementPlugin.PluginContainer|Calling InitializeComponent
2020-06-15 14:03:34.0729|ERROR|DonorManagementPlugin.PluginContainer|An unhandled exception occurred: 'Add value to collection of type 'DevExpress.Mvvm.UI.Interactivity.BehaviorCollection' threw an exception.' Line number '14' and line position '44'.
2020-06-15 14:03:34.0729|ERROR|DonorManagementPlugin.PluginContainer|System.Windows.Markup.XamlParseException: 'Add value to collection of type 'DevExpress.Mvvm.UI.Interactivity.BehaviorCollection' threw an exception.' Line number '14' and line position '44'. ---> WpfBindingErrors.BindingException: System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=; DataItem='NavigationFrame' (Name='nfFrame'); target element is 'FrameNavigationService' (HashCode=45706078); target property is 'Frame' (type 'NavigationFrame')
   at WpfBindingErrors.BindingExceptionThrower.OnErrorCatched(String message)
   at WpfBindingErrors.ObservableTraceListener.WriteLine(String message)
   at System.Diagnostics.TraceListener.TraceEvent(TraceEventCache eventCache, String source, TraceEventType eventType, Int32 id, String format, Object[] args)
   at System.Diagnostics.TraceSource.TraceEvent(TraceEventType eventType, Int32 id, String format, Object[] args)
   at MS.Internal.AvTrace.Trace(TraceEventType type, Int32 eventId, String message, String[] labels, Object[] parameters)
   at MS.Internal.TraceData.Trace(TraceEventType type, AvTraceDetails traceDetails, Object p1)
   at System.Windows.Data.BindingExpression.AttachToContext(AttachAttempt attempt)
   at System.Windows.Data.BindingExpression.OnInheritanceContextChanged(Object sender, EventArgs e)
   at System.Windows.WeakEventManager.ListenerList`1.DeliverEvent(Object sender, EventArgs e, Type managerType)
   at System.Windows.WeakEventManager.DeliverEvent(Object sender, EventArgs args)
   at MS.Internal.InheritanceContextChangedEventManager.OnInheritanceContextChanged(Object sender, EventArgs args)
   at System.Windows.DependencyObject.OnInheritanceContextChanged(EventArgs args)
   at System.Windows.Freezable.AddInheritanceContext(DependencyObject context, DependencyProperty property)
   at System.Windows.DependencyObject.ProvideSelfAsInheritanceContext(DependencyObject doValue, DependencyProperty dp)
   at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType)
   at System.Windows.DependencyObject.SetValueCommon(DependencyProperty dp, Object value, PropertyMetadata metadata, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType, Boolean isInternal)
   at System.Windows.DependencyObject.SetValue(DependencyProperty dp, Object value)
   at DevExpress.Xpf.WindowsUI.Navigation.FrameNavigationService.OnActualFrameChanged(NavigationFrame oldValue, NavigationFrame newValue)
   at DevExpress.Xpf.WindowsUI.Navigation.FrameNavigationService.set_ActualFrame(NavigationFrame value)
   at DevExpress.Xpf.WindowsUI.Navigation.FrameNavigationService.OnFrameChanged(NavigationFrame oldValue, NavigationFrame newValue)
   at DevExpress.Xpf.WindowsUI.Navigation.FrameNavigationService.OnFrameChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
   at System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
   at System.Windows.Freezable.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
   at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args)
   at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType)
   at System.Windows.DependencyObject.InvalidateProperty(DependencyProperty dp, Boolean preserveCurrentValue)
   at System.Windows.Data.BindingExpressionBase.Invalidate(Boolean isASubPropertyChange)
   at System.Windows.Data.BindingExpression.TransferValue(Object newValue, Boolean isASubPropertyChange)
   at System.Windows.Data.BindingExpression.Activate(Object item)
   at System.Windows.Data.BindingExpression.AttachToContext(AttachAttempt attempt)
   at System.Windows.Data.BindingExpression.OnInheritanceContextChanged(Object sender, EventArgs e)
   at System.Windows.WeakEventManager.ListenerList`1.DeliverEvent(Object sender, EventArgs e, Type managerType)
   at System.Windows.WeakEventManager.DeliverEvent(Object sender, EventArgs args)
   at MS.Internal.InheritanceContextChangedEventManager.OnInheritanceContextChanged(Object sender, EventArgs args)
   at System.Windows.DependencyObject.OnInheritanceContextChanged(EventArgs args)
   at System.Windows.Freezable.AddInheritanceContext(DependencyObject context, DependencyProperty property)
   at System.Windows.DependencyObject.ProvideSelfAsInheritanceContext(DependencyObject doValue, DependencyProperty dp)
   at System.Windows.Freezable.OnFreezablePropertyChanged(DependencyObject oldValue, DependencyObject newValue, DependencyProperty property)
   at System.Windows.FreezableCollection`1.AddWithoutFiringPublicEvents(T value)
   at System.Windows.FreezableCollection`1.AddHelper(T value)
   at System.Windows.FreezableCollection`1.System.Collections.IList.Add(Object value)
   at System.Xaml.Schema.XamlTypeInvoker.AddToCollection(Object instance, Object item)
   at MS.Internal.Xaml.Runtime.ClrObjectRuntime.Add(Object collection, XamlType collectionType, Object value, XamlType valueXamlType)
   --- End of inner exception stack trace ---
   at System.Windows.Markup.WpfXamlLoader.Load(XamlReader xamlReader, IXamlObjectWriterFactory writerFactory, Boolean skipJournaledProperties, Object rootObject, XamlObjectWriterSettings settings, Uri baseUri)
   at System.Windows.Markup.WpfXamlLoader.LoadBaml(XamlReader xamlReader, Boolean skipJournaledProperties, Object rootObject, XamlAccessLevel accessLevel, Uri baseUri)
   at System.Windows.Markup.XamlReader.LoadBaml(Stream stream, ParserContext parserContext, Object parent, Boolean closeStream)
   at System.Windows.Application.LoadComponent(Object component, Uri resourceLocator)
   at DonorManagementPlugin.PluginContainer.InitializeComponent()
   at DonorManagementPlugin.PluginContainer..ctor()

Hi,

2020-06-15 14:03:34.0729|ERROR|DonorManagementPlugin.PluginContainer|An unhandled exception occurred: ‘Add value to collection of type ‘DevExpress.Mvvm.UI.Interactivity.BehaviorCollection’ threw an exception.’ Line number ‘14’ and line position ‘44’.
2020-06-15 14:03:34.0729|ERROR|DonorManagementPlugin.PluginContainer|System.Windows.Markup.XamlParseException: ‘Add value to collection of type ‘DevExpress.Mvvm.UI.Interactivity.BehaviorCollection’ threw an exception.’ Line number ‘14’ and line position ‘44’. —> WpfBindingErrors.BindingException: System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=; DataItem=‘NavigationFrame’ (Name=‘nfFrame’); target element is ‘FrameNavigationService’ (HashCode=45706078); target property is ‘Frame’ (type ‘NavigationFrame’)

as I can see, you have some errors in DevEx.
Looks like you need to finalize it somehow for proper loading at second time


Edit: simple plugin w/o DevEx works w/o problem with this scenario:

1. Create a new instance.
2. Click a button to display a message or a dialog.  Dismiss
3. Select plugin from listbox and close pligin..
4. Mimimise and restore the main application to windows taskbar

when you repeat it several times

Hi,

We have refactored the code and moved the location of the FrameNavigation in the XAML in the DevExpress plugin to resolve this error.

I believe we now are seeing another problem since changing the domain.
Using hcdDefaultDomain it seems that the release and unload is not removing the plugin.

If we restart the plugin after loading data then the same data is present in the plugin when it is reloaded.

I have stepped through the ReleaseInstance and UnloadModule, no errors are raised.
UnloadModule is being called using the filename.

No errors are raised when we call LoadManagedModule the second time either
The plugin load is extremely quick on the second load, and montoring the resources the memory allocation of the host doesn’t drop as I would expect, and it seemed to previously, when the plugin is unloaded.

Another possible indication is that if I try to overwrite the .dll after the unload the file remains locked, usually this is possible

I am trying to reproduce this in a test application.
Could you investigate please.

Many thanks for your help so far, sorry to drag you back to D7 ! I’m not loving it either :slight_smile:
Martin.

Well, that’s the main reason why we do not use hcdDefaultDomain as a default plugin loading option.
In .NET it is not possible to unload as assembly after it has been loaded into an Application Domain. The only way to unload such assembly from memory is to destroy the AppDomain it is loaded into. Unfortunately the only way to destroy the default AppDomain is to stop its host process (read: to stop the host app in case of Hydra).
So it is expected that the plugin code will stay in memory even if it has been “unloaded” in case of default domain.

Thanks for your speedy reply

Is there any way we can return to using the hcdNewAppDomain and correct the issue originally reported on this thread which is causing the crash ? This would be an ideal solution for us.

Many thanks
Martin.

Hi,

I’ve tested simple wpf plugin with your host and LoadManagedModule(..., chbNewDomain.Checked);. it works w/o any issues.
looks like DevEx initializes some variables that cause original issue.