Unload child AppDomain that contains POS hardware causing CannotUnloadAppDomainException - c#

I am using .net 4.0, with POS.net 1.12 and I create a hardware class in a new child AppDomain so that any unhandled exceptions do not kill my parent AppDomain.
I can create the child AppDomain and make calls to it no problem. However, if I try to unload the AppDomain I get the exception "CannotUnloadAppDomainException".
I have googled the issue and the exception normally occurs when threads cannot be killed. I do not actually create any new threads in the child class.
I managed to pinpoint the piece of code that causes this error. If I create the POS hardware class and it only creates POS objects then it works fine. If, however, I call method "Open()" on any piece of hardware, then this exception occurs when unloading. Now before I attempt the unload, I close down all hardware and I have made sure the clean up code gets hit, so I am unsure what the issue is.
Here is the code to create and unload the AppDomain:
AppDomain hardwareDomain = AppDomain.CreateDomain("Hardware domain");
IHardwareManager hardwareManager =
(IHardwareManager)hardwareDomain.CreateInstanceFromAndUnwrap(typeof(OposHardwareManager).Assembly.Location,
typeof(OposHardwareManager).FullName);
hardwareManager.StartupHardware();
hardwareManager.CloseDownHardware();
hardwareManager = null;
// **** causes exception
AppDomain.Unload(hardwareDomain);
And here is the hardware class:
public class OposHardwareManager : MarshalByRefObject, IHardwareManager
{
private PosExplorer _posExplorer;
private PosPrinter _printer;
public void StartupHardware()
{
// create the hardware explorer
this._posExplorer = new PosExplorer();
// create and enable the printer
DeviceInfo printerInfo = this._posExplorer.GetDevice(DeviceType.PosPrinter);
PosDevice printerDevice = this._posExplorer.CreateInstance(printerInfo);
this._printer = (PosPrinter)printerDevice;
// ***** this line here, if run, causes the exception on unload
this._printer.Open();
this._printer.Claim(2000);
this._printer.DeviceEnabled = true;
}
public void CloseDownHardware()
{
this._printer.Release();
this._printer.Close();
this._printer = null;
this._posExplorer = null;
}
}
Any ideas?

If you are referencing a type in your creating domain (like you do with typeof(OposHardwareManager)), the assembly will be loaded in that domain too. When that happens, iow types crossing the domain boundary 'upwards', the created domain cannot be unloaded.
I suggest you do not reference the assembly containing OposHardwareManager and simply create it with the full qualified name instead. This may involve some refactoring.

In the documentation of AppDomain.Unload it is remarked that:
If a thread does not abort, for example because it is executing
unmanaged code, or because it is executing a finally block, then after
a period of time a CannotUnloadAppDomainException is thrown in the
thread that originally called Unload.
This is probably your case. Look at the documentation of PosDevice on how to properly release the resource.
Also note that an unhandled exception thrown by a thread created in the new AppDomain will crash your whole application. In the documentation of AppDomain.UnhandledException Event it is remarked that:
In the .NET Framework versions 1.0 and 1.1, an unhandled exception
that occurs in a thread other than the main application thread is
caught by the runtime and therefore does not cause the application to
terminate. Thus, it is possible for the UnhandledException event to be
raised without the application terminating. Starting with the .NET
Framework version 2.0, this backstop for unhandled exceptions in child
threads was removed, because the cumulative effect of such silent
failures included performance degradation, corrupted data, and
lockups, all of which were difficult to debug.

Not sure would this help but I founded the same error on Win 7 and XP. During app exit then the app crashed and error thrown. But the fault came from Report Viewer so when unload the form please make sure call
reportviewer.Reset();

Related

'System.Threading.Tasks.TaskCanceledException' occurred in WindowsBase.dll when closing application

I have this property in my viewmodel.
public bool IsKWH
{
get { return _isKwh; }
set
{
if (value.Equals(_isKwh)) return;
_isKwh = value;
NotifyOfPropertyChange(() => IsKWH);
}
}
Sometimes (~1 in 10 times) when I close down my application I get the following error in NotifyOfPropertyChange:
An exception of type 'System.Threading.Tasks.TaskCanceledException' occurred in WindowsBase.dll but was not handled in user code
Additional information: A task was canceled.
I have a System.Threading.Timer in my view model that is making a webservice call to update this and many other properties.
I am using Caliburn.Micro and it seems to have started happening when I updated from 1.5 to 2.0.
Is there anyway to prevent this error from occurring?
It is possible that intermittently your application fails to dispose of any secondary threads that it is using before the application closes. This can often cause an error message such as the one you posted. Could I suggest trying the following:
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
// close all active threads
Environment.Exit(0);
}
This should force the application to terminate all active threads before it closes. I recall having a similar problem and that particular little fix solved it. Might be worth giving it a try, let me know if it doesn't help and we can see what other solutions there might be. Hope this works for you.
FWIW, that fix didn't help me. the problem was coming from a 3rd party DLL that's dynamically loaded. I was unable to stop the exception from getting thrown, however I ignore the exception in the app exception handler:
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.UnhandledException += new UnhandledExceptionEventHandler(
(sender2, args) =>
{
Exception ex = (Exception)args.ExceptionObject;
// unloading dragon medical one
if (ex is TaskCanceledException)
return; // ignore

OS Loader Lock when doing managed-to-native interop

I am loading a native control (C++) into a WPF control using HwndHost. The HwndHost is defined as follows:
class ControlHost : System.Windows.Interop.HwndHost
{
public IntPtr Handle;
protected override HandleRef BuildWindowCore(HandleRef hwndParent)
{
// instantiate the native control
Handle = control.Handle;
return new HandleRef(this, control.Handle);
}
...
}
My WPF project has a System.Windows.Controls.Border named ControlHostElement. The general pattern is to get the handle for the ControlHostElement, instantiate the native control and and set it as a child element of the WPF control. This pattern is prescribed by MSDN here. I am triggering this with a button on the WPF page:
private void btnHwndHost_OnClick(object sender, RoutedEventArgs e)
{
myControlHost = new ControlHost();
ControlHostElement.Child = myControlHost;
}
The problem is that when I instantiate my native control, I get an OS Loader Lock error at the line where Child is assigned:
DLL 'my.dll' is attempting managed execution inside OS Loader lock. Do
not attempt to run managed code inside a DllMain or image
initialization function since doing so can cause the application to
hang.
I'm not sure how I'm inside the loader thread at this point, but I figure I should just spin up a new thread to perform the initialization and window handle assignment:
private void btnHwndHost_OnClick(object sender, RoutedEventArgs e)
{
Thread loadControlHostThread = new Thread(
new ThreadStart(this.loadControlHostThread_DoWork));
loadControlHostThread.SetApartmentState(ApartmentState.STA);
loadControlHostThread.Start();
}
void loadControlHostThread_DoWork()
{
myControlHost = new ControlHost();
ControlHostElement.Child = myControlHost;
}
No dice:
An unhandled exception of type 'System.InvalidOperationException'
occurred in WindowsBase.dll
Additional information: The calling thread cannot access this object
because a different thread owns it.
Fair enough. Maybe I should try asking the UI thread to do this work:
void loadControlHostThread_DoWork()
{
this.Dispatcher.Invoke((Action)(() =>
{
myControlHost = new ControlHost();
ControlHostElement.Child = myControlHost;
}));
}
That results in the same OS Loader Lock error. What is the correct way for me to initialize my native control?
I get an OS Loader Lock error
It is not an error, it is a warning. From an MDA, a Managed Debugger Assistant. They are little slivers of code that Microsoft inserted into the CLR and the debugger to produce warnings when it looks like your program is doing something wrong. The kind that doesn't produce an exception but makes your program hang-up or fail in a very difficult to diagnose way.
Loader lock certainly fits that pattern, it is a deadlock buried inside Windows internals. Associated with the loader, the part of the operating system that's responsible for loading DLLs and calling their DllMain() entrypoint. It takes an internal lock to ensure that the DllMain() functions are called one-at-a-time. It prevents re-entrancy problems, pretty comparable to the kind of trouble Application.DoEvents() causes. A deadlock on that lock is pretty hard to debug, the code is completely buried inside operating system as well as mysterious DllMain() functions you don't know anything about. Very high odds that a real deadlock would get you to tear your head-hair out in major clumps with little to show for it than a bald spot without that MDA.
Unfortunately the MDA tends to produce false warnings. It is not always aware that deadlock cannot actually happen. It is over-eager, a side-effect of it having to predict, crystal-ball style, that it might happen. Without otherwise being able to wire itself into the operating system internals to give you a guaranteed warning. The Windows group at Microsoft hasn't ever been that happy about accommodating managed code, Longhorn was a sore spot for quite a while. Loader lock was a big, big issue in .NET 1.0
It almost certainly is a false warning in your case, you can be dead-sure that the CLR is already loaded, your program could not possibly start otherwise.
Fortunately it is very simple to make it stop bugging you: Debug + Exceptions, open the Managed Debugging Assistants node and untick the "LoaderLock" checkbox. Very high odds that it will leave you in peace from there, allowing you to focus on testing your program.

VS2010 did not break debug on static constructor exception

I have a Windows Forms application with a single Editor class (that inherits from Form).
public partial class Editor : Form
{
public Editor()
{
InitializeComponent();
Load += Editor_Load;
}
private void Editor_Load(object sender, EventArgs e)
{
cmbConnections.DataSource = ConnectionManager.Connections;
cmbConnections.Visible = false;
}
}
Other than designer-generated code, this is the only code for the form (that contains only a single Combo Box (cmbConnections).
The ConnectionManager class is a static class with a static constructor. It's constructor does some initialization and then tests for some critical condition. If the condition is met, the constructor throws an exception. However, this exception does not break in the debugging mode in Visual Studio 2010. To test this, I've put only throw new Exception() in the ConnectionManager's static constructor. The ConnectionManager is used and therefor initialized (for the first time) in the Editor_Load event handler. Static constructor is called and exception thrown (visible only in output window). The rest of the Editor_Load event handler (cmbConnections.Visible = false;) is not executed, just as expected.
But what I don't understand is why did my VS2010 swallow the exception? It did not break the debug. It is not enclosed in any try/catch block. It continued with program execution with the main window. It almost seems as if the Editor_Load was executed on another thread.
I can see the messages in output window:
A first chance exception of type 'System.InvalidOperationException' occurred in Editor.exe
A first chance exception of type 'System.TypeInitializationException' occurred in Editor.exe
but the execution simply did not break in debug mode.
Here are some of my options that I believe may influence this behavior:
Project Properties->Build->General-> Optimize code is UNCHECKED.
Tools->Options->Debugging->General-> Enable Just My Code is CHECKED.
In exception settings, the checkbox for the "user-unhandled" is CHECKED.
Am I missing something? Is this behavior normal? I thought that VS2010 will throw on ANY unhandled exception. And here this one is unhandled and still does not break.
I think it is by design that you need to enable Managed (.NET) Exceptions 'Thrown' in the Exceptions Dialog (Ctrl-Alt-E).1
To avoid many spurious (handled) exceptions, I usually try to get close to the point where the initializer will be run and then check that checkbox just before continueing.
Also, if there are loader exceptions, be sure to check the nested inner exceptions or loader information in the exception: the exception itself is usually not that informative. I have frequently had to dig through 2 or more layers of wrapping exceptions in order to get at the actual error.
1 I can only guess as to why that is; My feeling is that the static type initializers are not considered to be run deterministically (many things could trigger it and the order is often undefined; it is just guaranteed that a type's static constructor will have been run before it is used, but it can be used at almost any point in the code, without you knowing or explicitely triggering that).
Therefore, it would be hard for the runtime to establish whether it was 'handled by user code' (no user should expect to handle it, because it doesn't know - deterministically - when the initializer will run).
However, this is conjecture on my part.

AccessViolationException in debugger with only managed code and WCF service

This application has a WCF web service that is called by a WinForms app. The WinForms app has a class WCFCache to manage data from the service. There is a section like this in that class to manage an optional custom configuration section that a subset of the machines have:
private bool? m_HasCustomConfiguration = null;
public bool HasCustomConfiguration
{
get
{
if (m_HasCustomConfiguration == null)
m_HasCustomConfiguration = (CustomConfiguration != null);
return (bool)m_HasCustomConfiguration;
}
}
private WCFService.CustomConfiguration m_CustomConfiguration = null;
public WCFService.CustomConfiguration CustomConfiguration
{
get
{
if (m_CustomConfiguration == null)
{
if (m_HasCustomConfiguration.HasValue
&& !m_HasCustomConfiguration.Value)
return null;
try
{
using (WCFService.WCFServiceClient wcf = new WCFService.WCFServiceClient())
{
m_CustomConfiguration =
wcf.GetCustomConfiguration(Machine.ProcessID);
// Above method returns null if no record exists.
m_HasCustomConfiguration = (m_CustomConfiguration != null);
}
} catch (Exception e) {
// Error logging & re-throw
}
}
return m_CustomConfiguration;
}
}
When I step through the debugger in code that calls either of the above properties like this:
if (!Program.WCFCache.HasCustomConfiguration)
return new List<CustomComponents>();
...it throws the following exception:
System.AccessViolationException was unhandled
Message="Attempted to read or write protected memory. This is often an indication that other memory is corrupt."
Source="System.Windows.Forms"
...
When I step onto the line containing the reference, there is a long pause, followed by a VS popup with the exception.
The exception doesn't appear when I just put a breakpoint after the above code has executed. It doesn't even appear when I put a breakpoint inside the accessors of the properties. It only occurs when I step onto a line with one of those properties from the outside. (So there is a workaround, but it can be a pain.)
Why is this happening? Can I stop it?
Edit: The whole application was written in the last year in 3.5 C#/.NET with WCF communicating between components; meaning, we don't have legacy unmanaged DLLs. Just two unmanaged calls: one to advapi32.dll when the WinForms app is loading, in the username detection procedure. The issue I'm having happens only in this one place in the code, in a place that is about as unrelated to the login section as you can get. The other is to kernel32.dll, in a GC force-flush long after anything is done with the results from calls like the one above.
Are you using any P/Invoke or other such native code? Odds are, that's where you should start looking.
This exception is a symptom of a larger problem, namely memory corruption (that what the exception says, after all). If this was a native application, you'd get a crash.
So, look at any native calls, make sure they're operating correctly, maybe run them under a debugger to try and trap the error closer to home.
Sorry, can't really give better advice given the circumstances.
I eventually found that others have encountered this situation and that it is likely a Visual Studio bug. I was using VS 2008 when the problem occurred.

How does SetUnhandledExceptionFilter work in .NET WinForms applications?

I am working on a project to enhance our production debugging capabilities. Our goal is to reliably produce a minidump on any unhandled exception, whether the exception is managed or unmanaged, and whether it occurs on a managed or unmanaged thread.
We use the excellent ClrDump library for this currently, but it does not quite provide the exact features we need, and I'd like to understand the mechanisms behind exception filtering, so I set out to try this for myself.
I started out by following this blog article to install an SEH handler myself: http://blogs.microsoft.co.il/blogs/sasha/archive/2007/12.aspx. This technique works for console applications, but when I try the same thing from a WinForms application, my filter is not called for any variety of unmanaged exceptions.
What can ClrDump be doing that I'm not doing? ClrDump produces dumps in all cases, so its exception filter must still be called...
Note: I'm aware of ADPlus's capabilities, and we've also considered using the AeDebug registry keys... These are also possibilities, but also have their tradeoffs.
Thanks,
Dave
// Code adapted from <http://blogs.microsoft.co.il/blogs/sasha/archive/2007/12.aspx>
LONG WINAPI MyExceptionFilter(__in struct _EXCEPTION_POINTERS *ExceptionInfo)
{
printf("Native exception filter: %X\n",ExceptionInfo->ExceptionRecord->ExceptionCode);
Beep(1000,1000);
Sleep(500);
Beep(1000,1000);
if(oldFilter_ == NULL)
{
return EXCEPTION_CONTINUE_SEARCH;
}
LONG ret = oldFilter_(ExceptionInfo);
printf("Other handler returned %d\n",ret);
return ret;
}
#pragma managed
namespace SEHInstaller
{
public ref class SEHInstall
{
public:
static void InstallHandler()
{
oldFilter_ = SetUnhandledExceptionFilter(MyExceptionFilter);
printf("Installed handler old=%x\n",oldFilter_);
}
};
}
Windows Forms has a built-in exception handler that does the following by default:
Catches an unhandled managed exception when:
no debugger attached, and
exception occurs during window message processing, and
jitDebugging = false in App.Config.
Shows dialog to user and prevents app termination.
You can disable the first behaviour by setting jitDebugging = true in App.Config. This means that your last chance to stop the app terminating is to catch the unhandled exception by registering for the event Application.ThreadException, e.g. in C#:
Application.ThreadException += new Threading.ThreadExceptionHandler(CatchFormsExceptions);
If you decide not to catch the unhandled exception here, then you will need to check and/or change the registry setting DbgJitDebugLaunchSetting under HKLM\Software.NetFramework. This has one of three values of which I'm aware:
0: shows user dialog asking "debug or terminate".
1: lets exception through for CLR to deal with.
2: launches debugger specified in DbgManagedDebugger registry key.
In Visual Studio, go to Tools>Options>Debugging>JIT to set this key to 0 or 2. But a value of 1 is usually what you want on an end-user's machine. Note that this registry key is acted on before the CLR unhandled exception event that you discuss.
Then you can set the native exception filter that you discussed.
If you want your GUI thread exceptions to work just like your-non GUI ones, so that they get handled the same way, you can do this:
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException);
Here's the background:
In a manged GUI app, by default, exceptions that originate in the GUI thread are handled by whatever is assigned to the Application.ThreadException, which you can customize like this:
Application.ThreadException +=
new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
Exceptions that originate in the other threads are handled by AppDomain.CurrentDomain.UnhandledException, which you can customize like this:
AppDomain.CurrentDomain.UnhandledException +=
new UnhandledExceptionEventHandler(Program.CurrentDomain_UnhandledException);
Assigning to UnHandledException works exactly like calling Win32 SetUnhandledExceptionFilter.
If you goal is to create minidumps and then use them, you'll need to use Debugging Tools for Windows, sos.dll. You'll need to produce minidumps MiniDumpWithFullMemory.
And then, even then, you probably won't have everything you might want. System.Diagnostics.StackTrace to get the call managed call stack.
SetUnhandledExceptionFilter installs a handler that is invoked when a Win32-excpetion reaches the top of a threads callstack without being handled.
In many language runtimes including managed, language exceptions are implemented using Win32 exceptions. But, the managed runtime will have a top level __try __catch(...) block at the top of each thread that will catch any win32 to runtime exceptions and process them without letting them escape to Win32's top level handler.
Knowledge of the specific runtime would be necessary to inject a handler at this level because the exceptions will never be allowed to escape to Win32's TheadProc handler.

Categories

Resources