Loader lock error - c#

I am building on C++ dll, by writing code in C#.
I get an error, saying
LoaderLock was detected Message:
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 tried seraching what this error exactly means, but I am drawing pointless articles, mostly saying that it's just a warning, and I should switch that off in Visual Studio.
The other solutions seem to be due to ITunes, or this problem occurring when programming with DirectX. My problem is connected to neither.
Can anybody explain, what this actually means?

you need to go to menu Debug -> Exceptions, open the Managed Debugging Assistants, find LoaderLock and uncheck

The general idea of loader lock:
The system runs the code in DllMain inside a lock (as in - synchronization lock). Therefore, running non-trivial code inside DllMain is "asking for a deadlock", as described here.
The question is, why are you trying to run code inside DllMain? Is it crucial that this code run inside the context of DllMain or can you spawn a new thread and run the code in it, and not wait for the code to finish execution inside DllMain?
I believe that the problem with manged code specifically, is that running managed code might involves loading the CLR and suchlike and there's no knowing what could happen there that would result in a deadlock... I would not heed the advice of "disable this warning" if I were you because most chances are you'll find your applications hangs unexpectedly under some scenarios.

UPDATE FOR .NET 4.0 AND MORE RECENT FRAMEWORKS
This is an old question asked at the time of .Net 2.0, when support for mixed mode DLLs had serious initialization problems, prone to random deadlocks. As of .Net 4.0, the initialization of mixed mode DLLs has changed. Now there are two separate stages of initialization:
Native initialization, called at the DLL's entry point, which includes native C++ run-time setup and execution of your DllMain method.
Managed initialization, executed automatically by system loader.
Since step #2 is performed outside of the Loader Lock, there is no deadlocks. The details are described at Initialization of Mixed Assemblies.
To ensure your mixed mode assembly can be loaded from a native executable, the only thing you need to check is that DllMain method is declared as native code. #pragma unmanaged could help here:
#pragma unmanaged
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
... // your implementation here
}
It is also important that any code that DllMain might call directly or indirectly is also unmanaged. It makes sense to limit the type of functionality used by DllMain so you trace all code reachable from DllMain and ensure it is all compiled with #pragma unmanaged.
Compiler helps a little by giving you warining C4747 if it detects that DllMain is not declared as unmanaged:
1> Generating Code...
1>E:\src\mixedmodedll\dllmain.cpp : warning C4747: Calling managed 'DllMain': Managed code may not be run under loader lock, including the DLL entrypoint and calls reached from the DLL entrypoint
However compiler won't generate any warnings if DllMain indirectly calls some other managed function, so you need to ensure that never happens, otherwise your application could deadlock randomly.

kindly remind those VS2017 users that you need to disable "exception helper" instead of "exception assistant"(before VS2017) to prevent from loader lock error, which setting path is Debug->Exception. Just ran int to this problem and wasted 2 hours searching for solutions...

Press ctr d+e Then Expend Managed Debugging Assistants Node. Then Unchecked the LoaderLock.
Hope this will help you.

I recently got this error while creating an instance of an COM-Object written in native code:
m_ComObject = Activator.CreateInstance(Type.GetTypeFromProgID("Fancy.McDancy"));
This led to the described error. A "LoaderLock was detected"-Exception was thrown.
I overcame this error by creating the object-instance in an extra thread:
ThreadStart threadRef = new ThreadStart(delegate { m_ComObject = Activator.CreateInstance(Type.GetTypeFromProgID("Fancy.McDancy")); });
Thread myThread = new Thread(threadRef);
myThread.Start();
myThread.Join(); // for synchronization

I'm building a C++ CLR DLL (MSVS2015) that has to make calls into an unmanaged DLL and define unmanaged code. I use #pragma managed and #pragma unmanaged to control what mode it is in for a given area of the code.
In my case I simply put #pragma unmanaged in front of my DllMain() and this solved the problem.
It seemed to be thinking I wanted a managed version of DllMain().

The setting path in my visual studio 2017 instance is Debug -> Windows -> Exception Settings . The exception settings "window" showed up in the bottom tab group (as opposed to a separate window), took me a while to notice it. Search for "loader".

This problem occurs because of the way in which the debugger in Visual Studio runs managed applications that use Microsoft Foundation Classes version 8.0 in one or more DLL files.
Have a thorough reading at: http://msdn.microsoft.com/en-us/library/aa290048(vs.71).aspx

Related

C++ DLL does not unload with AppDomain

I have a C# plugin that uses a separate C++ DLL. The only reference to that DLL is from within the plugin itself. The parent application loads all plugins in their own AppDomain and unloads this AppDomain when the plugin is unloaded.
I have checked, and I definitely see the application's memory drop when I unload the plugin. I am also able to delete all of the managed assemblies that were loaded. The problem is that when I try to delete the native DLL I just keep getting Access Denied until I close the whole application.
I've been looking at this for a while, but I still can't figure out why just this DLL stays in memory.
AppDomains are a pure managed code construct. Nothing like that exists in native code, nor does Windows have any idea about it. So the scope for a loaded native DLL is the process. Technically, the pinvoke marshaller could reference count the DLL and keep track exactly which AppDomain triggered the load of the DLL. It however cannot tell whether any native code is running that uses that DLL. Native code that could be started by a call made from code in another AppDomain, possibly indirectly through a marshaled delegate.
Clearly disaster strikes if the AppDomain manager unloads a DLL that's used that way, that's a nasty and impossible to diagnose AccessViolation. Particularly nasty since it can trigger a long time after the AppDomain got unloaded.
So the marshaller doesn't implement that kind of counting, the DLL stays loaded. Only you can provide the guarantee that this can't happen, you have some measure of control over exactly what code runs in the DLL and how it gets started. You can force the DLL to unload but it requires a hack. Pinvoke LoadLibrary() yourself to get a handle to the DLL. And pinvoke FreeLibrary() twice to get it unloaded forcibly. Neither Windows nor the CLR can't see that you are cheating. You must ensure that the DLL can't be used after this.
AFAIK (under the hood) native DLLs need to be loaded via Win32 API LoadLibrary... which loads them directly into the process memory - in case of a .NET application that is not specific to an AppDomain... LoadLibrary knows absolutely nothing about AppDomain (which is purely .NET-specific)... thus unloading the AppDomain doesn't necessarily unload native DLLs...
Interesting discussions regarding this situation:
http://clrinterop.codeplex.com/discussions/61817
http://www.mofeel.net/61-microsoft-public-dotnet-framework-interop/1940.aspx
IF you can change the implementation of the respective plugin then you would implement "late native binding" which would solve the problem you see:
http://blogs.msdn.com/b/junfeng/archive/2004/07/14/181932.aspx
http://www.codeproject.com/KB/cs/dyninvok.aspx
http://pinvoke.net/default.aspx/kernel32/GetPRocAddress.html
http://www.pinvoke.net/default.aspx/kernel32.loadlibrary

Weird crash when debugging COM object destructor

My application is a mix of C# and C++ code. Startup module written in C# loads during initialization phase C++ module through COM (Component Object Model) mechanism. All was functioning correctly until I decided to add to C# part a wcf service. All wcf service calls are routed to C++ code using COM. After adding some new methods I noticed memory leaks in output window. So I added breakpoint to desctructor of C++ class as can be seen from screenshot. From this point on weird things started to happen. After program reaches breakpoint it unexpectedly crashes. First weird thing is that when I run program without breakpoint being set it ends graciously. Second weird thing is that the way program crashes is as if it were running without debugger. After clicking on button "Open in debugger" (or something like this) I get error message: "Program is already opened under debugger." None message in output window that could point me to the source of the error, none suspicious code.
When adding message box to destructor beginning it displays for fraction of second and then whole application closes (without adding user opportunity to read whats displayed in message box). Desperately searching for any clue.
P.S. Problems occurs only when wcf method was called at least once. Doesn't depend if program flow in this particular call was routed to C++ level or not.
When calling C# from C++ sometimes the garbage collector doesn't properly get called before program end. Try forcing garbage collection at the end of your C# code.
Resolved by following code:
public void Dispose()
{
Marshal.Release(internal_interface_ptr);
internal_interface_ptr = IntPtr.Zero;
Marshal.ReleaseComObject(internal_interface);
Marshal.ReleaseComObject(internal_interface);
internal_interface = null;
}
Beside this one other reference was hanging in C++ code. So to make conclusion, main mistake on my part was forgetting to explicitly release COM object in C# code. Even if garbage collector takes task of managing memory this isn't true for modules written in other programming languages. COM destructor was called very lately when particular dynamic linked library was to be unloaded from memory and this caused problems. Hope I explained it sufficient clearly.

Diagnose/Debug potential stack corruption .NET application

I think I have a curly one here... I have an WinForms application that crashes fairly regularly every hour or so when running as an x64 process. I suspect this is due to stack corruption and would like to know if anyone has seen a similar issue or has some advice for diagnosing and detecting the issue.
The program in question has no visible UI. It's just a message window that sits in the background and acts as a sort of 'middleware' between our other client programs and a server.
It dies in different ways on different machines. Sometimes it's an 'APPCRASH' dialog that reports a fault in ntdll.dll. Sometimes it's an 'APPCRASH' that reports our own dll as the culprit. Sometimes it's just a silent death. Sometimes our unhandled exception hook logs the error, sometimes it doesn't.
In the cases where Windows Error Reporting kicks in, I've examined memory dumps from several different crash scenarios and found the same Managed exception in memory each time. This is the same exception I see reported as an unhandled exception in the cases where we it logs before it dies.
I've also been lucky (?) enough to have the application crash while I was actively debugging with Visual Studio - and saw that same exception take down the program.
Now here's the kicker. This particular exception was thrown, caught and swallowed in the first few seconds of the program's life. I have verified this with additional trace logging and I have taken memory dumps of the application a couple of minutes after application startup and verified that exception is still sitting there in the heap somewhere. I've also run a memory profiler over the application and used that to verify that no other .NET object had a reference to it.
The code in question looks a bit like this (vastly simplified, but maintains the key points of flow control)
public class AClass
{
public object FindAThing(string key)
{
object retVal = null;
Collection<Place> places= GetPlaces();
foreach (Place place in places)
{
try
{
retval = place.FindThing(key);
break;
}
catch {} // Guaranteed to only be a 'NotFound' exception
}
return retval;
}
}
public class Place
{
public object FindThing(string key)
{
bool found = InternalContains(key); // <snip> some complex if/else logic
if (code == success)
return InternalFetch(key);
throw new NotFoundException(/*UsefulInfo*/);
}
}
The stack trace I see, both in the event log and when looking at the heap with windbg looks a bit like this.
Company.NotFoundException:
Place.FindThing()
AClass.FindAThing()
Now... to me that reeks of something like stack corruption. The exception is thrown and caught while the application is starting up. But the pointer to it survives on the stack for an hour or more, like a bullet in the brain, and then suddenly breaches a crucial artery, and the application dies in a puddle.
Extra clues:
The code within 'InternalFetch' uses some Marshal.[Alloc/Free]CoTask and pinvoke code. I have run FxCop over it looking for portability issues, and found nothing.
This particular manifestation of the issue is only affecting x64 code built in release mode (with code optimization on). The code I listed for the 'Place.Find' method reflects the optimized .NET code. The unoptimized code returns the found object as the last statement, not 'throw exception'.
We make some COM calls during startup before the above code is run... and in a scenario where the above problem is going to manifest, the very first COM call fails. (Exception is caught and swallowed). I have commented out that particular COM call, and it does not stop the exception sticking around on the heap.
The problem might also affect 32 bit systems, but if it does - then the problem does not manifest in the same spot. I was only sent (typical users!) a few pixels worth of a screen shot of an 'APP CRASH' dialog, but the one thing I could make out was 'StackHash_2264' in the faulting module field.
EDIT:
Breakthrough!
I have narrowed down the problem to a particular call to SetTimer.
The pInvoke looks like this:
[DllImport("user32")]
internal static extern IntPtr SetTimer(IntPtr hwnd, IntPtr nIDEvent, int uElapse, TimerProc CB);
internal delegate void TimerProc(IntPtr hWnd, uint nMsg, IntPtr nIDEvent, int dwTime);
There is a particular class that starts a timer in its constructor. Any timers set before that object is constructed work. Any timers set after that object is constructed work. Any timer set during that constructor causes the application to crash, more often than not. (I have a laptop that crashes maybe 95% of the time, but my desktop only crashes 10% of the time).
Whether the interval is set to 1 hour, or 1 second, seems to make no different. The application dies when the timer is due - usually by throwing some previously handled exception as described above. The callback does not actually get executed. If I set the same timer on the very next line of managed code after the constructor returns - all is fine and happy.
I have had a debugger attached when the bad timer was about to fire, and it caused an access violation in 'DispatchMessage'. The timer callback was never called. I have enabled the MDAs that relate to managed callbacks being garbage collected, and it isn't triggering. I have examined the objects with sos and verified that the callback still existed in memory, and that the address it pointed to was the correct callback function.
If I run '!analyze -v' at this point, it usually (but not always) reports something along the lines of 'ERROR_SXS_CORRUPT_ACTIVATION_STACK'
Replacing the call to SetTimer with Microsoft's 'System.Windows.Forms.Timer' class also stops the crash. I've used a Reflector on the class and can see internally it still calls SetTimer - but does not register a procedure. Instead it has a native window that receives the callback. It's pInvoke definition actually looks wrong... it uses 'ints' for the eventId, where MSDN documentation says it should be a UIntPtr.
Our own code originally also used 'int' for nIDEvent rather than IntPtr - I changed it during the course of this investigation - but the crash continued both before and after this declaration change. So the only real difference that I can see is that we are registering a callback, and the Windows class is not.
So... at this stage I can 'fix' the problem by shuffing one particular call to SetTimer to a slightly different spot. But I am still no closer to actually understanding what is so special about starting the timer within that constructor that causes this error. And I dearly would like to understand the root cause of this issue.
Just briefly thinking about it it sounds like an x64 interop issue (i.e., calling x32 native functions from x64 managed code is fraught with danger). Does the problem go away if you force your application to compile as x32 platform from within project properties?
You can read suggestions on forcing x32 compile during x32/x64 development on Dotnetrocks. Richard Campbell's suggestion is that Visual Studio should default to x32 platform and not AnyCPU.
http://www.dotnetrocks.com/default.aspx?showNum=341 (transcript).
With regard to advanced debugging, I have not had a chance to debug x64 interop code, but i hear that this book is an great resource: Advanced .NET Debugging.
Finally, one thing you might try is force Visual Studio to break when an exception is thrown.
Use something like DebugDiag for x64 or Windbg to write a dump on Kernel32!TerminateProcess and second chance exception on .NET which should give you the actual .excr context frame of the exception that occurred.
This should help you in identifying the call-stack for the process terminate.
IMO it could be mostly because of PInvoke calls. You could use Managed Debugging Assistants to debug these issues.
If MDA is used along with Windbg it would give out messages that would be helpful in debugging
Also I have found tools from the http://clrinterop.codeplex.com/ team are extremely handy when dealing with interop
EDIT
This should give an answer why it is not working in 64 bit Issue with callback method in SetTimer Windows API called from C# code .
This does sound like a corruption issue. I would go through all of your interop calls and ensure that all of the parameters to the DllImport'ed functions are the correct types. For exmaple, using an int in place of an IntPtr will work in 32 bit code but can crash 64 bit.
I would use a site like PInvoke.net to verify all of the signatures.

Odd problem with System.AccessViolationException

I have an asp.net (3.5) web application.
In one page i use an unmanaged C library (a simulator) that produces a set of results based on some input.
When i've set the debug="false" in web.config (Release mode) that call will result in a System.AccessViolationException. If i am in the debugger, or at least set debug="true" in web.config, that exception will never appear.
Because of the nature of the bug i placed the call inside a try-catch to log the exception and then the exception does not appear!
Is there some magical work on protected memory space when in debug mode and/or in a try-catch?
AccessViolationException in this context probably means your unmanaged C code is screwing up. It's overwriting the heap or something.
Keep in mind that many pieces of code were never written to be run in a multi-threaded environment like that of ASP.NET. They were never even tested in such an environment, or were only tested using some "desktop" form of multi-threading that does not apply to ASP.NET.
I had a problem like this once. A third-party DLL which claimed to be thread-safe was very unsafe. By attaching an unmanaged debugger to the ASP.NET worker process, it was possible to see that the application was writing all over the C runtime library heap, and the heap was complaining bitterly about it. And nothing was listening to the complaints.
It was necessary to wrap calls to this code in a lock block - to ensure that only one thread could call it at a time. This was sufficient to prevent all of the crashes, even under load.
This still might not suffice for all unmanaged code. A piece of code that assumes all calls will occur on the same thread, or that all calls from the same "session" occur on the same thread, will be disappointed, and may very well crash or do something worse. In that case, you might need to move that code into a separate Windows Service which only allows one single thread to access that library, ever.

Calling a c# .dll from native visual c++ code

the system I'm working with consists of:
A front-end application written in most likely VB or else VC++ (don't know, don't and can't have the sources for it)
An unmanaged VC++ .dll
A C# .dll
The application calls the first dll, the first dll calls different methods from the second one.
In order to make the first dll able to see and call the C# code I followed this guide:
http://support.microsoft.com/kb/828736
The only difference is that i am not compiling with /clr:OldSyntax, if I do then changing the other dependant compiling options makes the first dll load incorrectly from the application.
Everything compiles smoothly; the whole setup even worked fine initially, however after completely developing my code across the two dlls I now get an error in the application. The error is:
Run-time error '-2147417848 (80010108)':
Automation Error
The object invoked has disconnected from its clients.
And occurs when the following line is executed in the first dll:
MyManagedInterfacePtr ptrName(__uuidof(MyManagedClass));
I tried reproducing a fully working setup but without success.
Any ideas on how the heck I managed to do it in the first place?
Or alternatively on other approaches for making the two dlls work together?
Thanks in advance!
It is a low-level COM error, associated with RPC. That gets normally used in out-of-process servers, but that doesn't sound like your setup. It would also be used if you make calls on a COM interface from another thread. One possible cause is that the thread that created the COM object was allowed to exit, calling CoUninitialize and tearing down the COM object. A subsequent call made from another thread would generate this error. Getting reference counting wrong (calling Release too often) could cause this too.
Tackle this by carefully tracing which threads create a COM object and how long they survive.

Categories

Resources