Is there any way to ensure a function is compiled JIT? - c#

I have a function that I want to be sure is compiled JIT (i.e. right before it's called). Are there attributes or assembly settings that will ensure this? If not, then how can I guarantee that a function is compiled JIT?
Thanks!
EDIT:
I want to do this to prevent my application from crashing due to a missing referenced assembly. If my function is compiled JIT, I can wrap the function call that references the missing assembly in a try...catch block and gracefully handle the situation.
It is my understanding that there could be times when whole classes (or even the whole application) could be Jitted - this would cause an error I couldn't possibly catch.

If I read this correctly, you are worried about errors occurring when a class/method is first compiled. This requires awareness of the boundaries. It is obtainable with an extra layer.
If something is 'wrong with SuspectType (ie a required assembly not loading), the try/catch in the following is of no use because the Jitting of Scenario1() itself will fail.
void Scenario1()
{
try
{
var x = new SuspectType();
...
}
catch (..) { ... }
}
It could be rewritten as
void Scenario1a()
{
try
{
Scenario1b();
}
catch (..) { ... }
}
void Scenario1b()
{
var x = new SuspectType();
...
}
But, per Jon Skeet's comment, I'm not sure if this holds for the CFx.

I may be answering the wrong question, but it looks like you mainly want to be able to intercept assembly load failures (whole classes being JITted defeat the try/catch guards around the calls but that's a side effect of using explicit guards around method calls).
If you want to catch assembly resolution woes, instead of specifying a try/catch around every possible call, you could just listen to the global AssemblyResolve event and respond to the assembly loading failures (we're talking about .Net assemblies here, native dll's load failures would have to be tracked with a different mechanism).
static void Main()
{
AppDomain.CurrentDomain.AssemblyResolve += OnResolveFailure;
//...
}
static Assembly OnResolveFailure(object sender, ResolveEventArgs args)
{
//Do something here...
}
The downside of this is you can't do much, except looking for the assembly somewhere else (or logging the error). Specific and graceful logic when a resolution fails is not provided with this way of catching load failures.

Is this something that your app needs to be able to resolve on it's own, or are you debugging some kind of assembly load problem right now?
If the latter, have a look at the fusion log. This is log that is generated by the subsystem that probes for and loads assemblies at run time.
Here's an article: http://www.hanselman.com/blog/BackToBasicsUsingFusionLogViewerToDebugObscureLoaderErrors.aspx

Related

Why does Assembly.Load seem to not affect the current thread when resolving references (not through reflection)?

I apologize in advance if the title doesn't make sense. I'm very new to appdomains and assembly loading and don't really know how to state what I'm trying to ask.
I have been fiddling around with loading embedded DLLs into an application during runtime and I can't seem to figure out why it works one way but not the other. It seems like if you try to load DLLs (from a byte array) into the current appdomain, any objects/threads created after that will be able to resolve references against the newly loaded library, however objects in the original context will not resolve against the newly loaded library.
Here is my example library that will be loaded from as an embedded resource during runtime (requires a reference to the WPF PresentationFramework.dll for MessageBox):
namespace LoaderLibrary
{
public class LoaderLibrary
{
public static void Test()
{
System.Windows.MessageBox.Show("success");
}
}
}
In my console app .csproj file I manually add the following embedded resource for that project and include a project reference to LoaderLibrary as well:
<ItemGroup>
<EmbeddedResource Include="..\LoaderLibrary\bin\$(Configuration)\LoaderLibrary.dll">
<LogicalName>EmbeddedResource.LoaderLibrary.dll</LogicalName>
</EmbeddedResource>
</ItemGroup>
Here is the code for my console app that loads that library (requires a project reference to the LoaderLibrary csproj) ALSO: Need to set CopyLocal to false for LoaderLibrary reference:
namespace AssemblyLoaderTest
{
class Program
{
static void Main(string[] args)
{
EmbeddedAssembly.Load("EmbeddedResource.LoaderLibrary.dll");
System.AppDomain.CurrentDomain.AssemblyResolve += (s, a) => { return EmbeddedAssembly.Get(a.Name); };
var app = new TestApp();
}
}
public class TestApp
{
public TestApp()
{
LoaderLibrary.LoaderLibrary.Test();
}
}
public class EmbeddedAssembly
{
static System.Collections.Generic.Dictionary<string, System.Reflection.Assembly> assemblies = new System.Collections.Generic.Dictionary<string, System.Reflection.Assembly>();
public static void Load(string embeddedResource)
{
using (System.IO.Stream stm = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(embeddedResource))
using (var mstream = new System.IO.MemoryStream())
{
stm.CopyTo(mstream);
var assembly = System.Reflection.Assembly.Load(mstream.ToArray());
assemblies.Add(assembly.FullName, assembly);
return;
}
}
public static System.Reflection.Assembly Get(string assemblyFullName)
{
return (assemblies.Count == 0 || !assemblies.ContainsKey(assemblyFullName)) ? null : assemblies[assemblyFullName];
}
}
}
This code is able to successfully load and execute the LoaderLibrary.LoaderLibrary.Test() function.
My question is why does the following not work?
static void Main(string[] args)
{
EmbeddedAssembly.Load("EmbeddedResource.LoaderLibrary.dll");
System.AppDomain.CurrentDomain.AssemblyResolve += (s, a) => { return EmbeddedAssembly.Get(a.Name); };
LoaderLibrary.LoaderLibrary.Test(); // very unhappy line of code
}
This also doesn't work:
static void Main(string[] args)
{
EmbeddedAssembly.Load("EmbeddedResource.LoaderLibrary.dll");
System.AppDomain.CurrentDomain.AssemblyResolve += (s, a) => { return EmbeddedAssembly.Get(a.Name); };
var app = new TestApp();
LoaderLibrary.LoaderLibrary.Test(); // very unhappy line of code
}
Big thanks to Hans Passant and dthorpe for explaining what was happening.
I found dthorpe's great explanation on how the JIT compiler works here: C# JIT compiling and .NET
To quote dthorpe here:
Yes, JIT'ing IL code involves translating the IL into native machine
instructions.
Yes, the .NET runtime interacts with the JIT'ed native machine code,
in the sense that the runtime owns the memory blocks occupied by the
native machine code, the runtime calls into the native machine code,
etc.
You are correct that the .NET runtime does not interpret the IL code
in your assemblies.
What happens is when execution reaches a function or code block (like,
an else clause of an if block) that has not yet been JIT compiled into
native machine code, the JIT'r is invoked to compile that block of IL
into native machine code. When that's done, program execution enters
the freshly emitted machine code to execute it's program logic. If
while executing that native machine code execution reaches a function
call to a function that has not yet been compiled to machine code, the
JIT'r is invoked to compile that function "just in time". And so on.
The JIT'r doesn't necessarily compile all the logic of a function body
into machine code at once. If the function has if statements, the
statement blocks of the if or else clauses may not be JIT compiled
until execution actually passes through that block. Code paths that
have not executed remain in IL form until they do execute.
The compiled native machine code is kept in memory so that it can be
used again the next time that section of code executes. The second
time you call a function it will run faster than the first time you
call it because no JIT step is necessary the second time around.
In desktop .NET, the native machine code is kept in memory for the
lifetime of the appdomain. In .NET CF, the native machine code may be
thrown away if the application is running low on memory. It will be
JIT compiled again from the original IL code the next time execution
passes through that code.
With the information from that question, and the information from Hans Passant, it is very clear what is happening:
The JIT compiler attempts to convert the entire entry point code
block (in this case my Main() function) into native code. This
requires that it resolve all references.
The embedded assembly LoaderLibrary.dll has NOT been loaded into the
AppDomain yet because the code that does this is defined in the
Main() function (and it can't execute code that hasn't been compiled).
The JIT compiler attempts to resolve the reference to
LoaderLibrary.dll by searching the AppDomain, Global Assembly Cache,
App.config/Web.config, and probing (environment PATH, current
working directory, etc.) More info on this can be found in the MSDN
article here: How the Runtime Locates Assemblies
The JIT compiler fails to resolve the reference to
LoaderLibrary.LoaderLibrary.Test(); and results in the error
Could not load file or assembly or one of its dependencies
The way to get around this as suggested by Hans Passant is to load your assemblies in a code block that gets JIT compiled earlier than any code block that references those assemblies.
By adding the [MethodImpl(MethodImplOptions.NoInlining)] to methods that reference the dynamically loaded assemblies, it will prevent the optimizer from trying to inline the method code.

Is it possible to not break execution flow on certain exceptions but break on others - and if so, how?

I need to call several methods from an external framework - or rather I am writing a wrapper around it for other users to call methods from this framework in a non-predetermined order. Now some methods of the framework will throw exceptions, even though no "real" error occured. Basically they are supposed to be internal exceptions just to notify whoever that the action to be performed has already been performed before. For example: that a file has been loaded. It wont hurt to load the file another time, so for all I care this "error" is no error at all. So I need to continue on this exception, but I also need to catch other, real exceptions, such as when the framework, which connects to clients and stuff, cannot do so.
Below I have some (extremely simplified) example code. Obviously that code wont compile because the code for the custom exceptions is missing. Also in real life the code is spread over three assemblies. This means, that I cannot wrap the exception handler around those framework methods which will throw InternalFrameworkException() only. I can only wrap it around the whole SomeMethod(). As I wrote, this is an extremely simplified example.
Is there any way to handle the RealException()s but continue the InternalFrameworkException()s without using PostSharp as mentioned here? Note that this is not about letting the InternalFrameworkException() fall through, but they should actually not break out of the try{} block at all.
namespace ExceptionTest
{
using System;
internal class Program
{
private static void Main(string[] args)
{
try
{
SomeMethod();
}
catch (InternalFrameworkException exception)
{
// Do not actually catch it - but also dont break the
// execution of "SomeMethod()".
// Actually I never want to end up here...
}
catch (RealException exception)
{
// Break the execution of SomeMethod() as usual.
throw;
}
catch (Exception exception)
{
// Again, break the execution of SomeMethod() as usual.
throw;
}
finally
{
// Clean up.
}
}
#region == Method is actually contained in another assembly referencing this assembly ===
private static void SomeMethod()
{
// Should break if uncommented.
// MethodThrowingProperException();
// Should not break.
MethodThrowingInternalExceptionOrRatherContinuableError();
// Should execute, even if previously an internal framework error happened.
MethodNotThrowingException();
}
#endregion
#region ===== Framework methods, they are contained in a foreign dll =====
private static void MethodThrowingProperException()
{
// Something happened which should break execution of the
// application using the framework
throw new RealException();
}
private static void MethodThrowingInternalExceptionOrRatherContinuableError()
{
// Perform some stuff which might lead to a resumable error,
// or rather an error which should not break the continuation
// of the application. I.e. initializing a value which is
// already initialized. The point is to tell the application using
// this framework that the value is already initialized, but
// as this wont influence the execution at all. So its rather
// a notification.
throw new InternalFrameworkException();
}
private static void MethodNotThrowingException()
{
// Well, just do some stuff.
}
#endregion
}
}
Edit: I did try the example in the post I already linked above, and it works like a charm ... when using it in SomeMethod() only. I could theoretically implement this as I am wrapping all the methods that are called in SomeMethod() before exposing them to the final assembly, but I dislike this approach, because it will give my code unnessessary complexity.
When an exception is thrown, the execution flow is broken. You can catch the exception or not but you cannot "continue" after the exception is thrown.
You can split your logic into parts and continue to the next part when one throws an exception, though.
I'm not sure of a way apart from an AOP approach in this case. Given that you are unable to change SomeMethod() or any of the methods it calls, you will need to look at adorning the called methods like MethodThrowingInternalExceptionOrRatherContinuableError() with an aspect that catches the 'continuable' exceptions.
The aspect would effectively wrap the method call in a try{...} catch(InternalFrameworkException) (or similar catchable exception) block.
As you have already noted, you are unable to drop back into a method once it has thrown an exception, even if the caller catches the exception in a catch() block, so you need to inject into the methods you are calling, which an AOP framework like PostSharp will allow you to do.
I have solved similar problem by wrapping the calls to InternalFrameworkMethod() in try-catch(InternalFrameworkException) blocks and calling it somethig like InternalFrameworkMethodSafe() and then in SomeMethod call the treated InternalFrameworkMethodSafe().
void InternalFrameworkMethodSafe()
{
try
{
InternalFrameworkMethod();
}
catch(InternalFrameworkException e)
{
Trace.Write("error in internal method" + e);
}
}
void SomeMethod()
{
...
InternalFrameworkMethodSafe();
...
}
It may not work in your case if the internal framework is in wrong state and not able to continue.

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.

Is there an equivalent of Application_Start for a class library in c#

I would like to execute certain code in a class library when it is instantiated from another assembly. Is there an entry point or bootstrap for a class library?
I thought that a static method Main would do the trick but I was wrong.
Applications for this might be configuring and instantiating a logger singleton, unhandled exception handler, etc.
A library as it is, has not an starting point. When you are instancing a class of a library the first instruction you call is the constructor of the class (new) and its base constructors if they are on the constructor definition.
AppDomain.AssemblyLoad Event which occurs when an assembly is loaded. Probably that can be used to call an initialize method in your class library.
public static void Main()
{
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.AssemblyLoad += new AssemblyLoadEventHandler(MyAssemblyLoadEventHandler);
}
static void MyAssemblyLoadEventHandler(object sender, AssemblyLoadEventArgs args)
{
Console.WriteLine("ASSEMBLY LOADED: " + args.LoadedAssembly.FullName);
//If this is the assembly that you want to call an initialize method..
}
Below are two similar threads
how to write class lib's assembly load/init event handler
.Net: Running code when assembly is loaded
The best and safe way is to design your library so that the caller will initialize your library when they know they can.
When an assembly is loaded, the CLR employes a lot of machinery to have the job done, starting from how the inner platform is designed to load modules up to the CLR itself. Each involved actor has their own limitations.
Executing code when a module is loaded is not the best practice on Win32 for the same reason: you cannot know what your caller is doing; also, the changes your doing could possibly alter the current AppDomain, but may not plbe propagated in all the other AppDomain of the application.
A conscious initialization method is the cleanest way to let the caller to control the initialization of your assembly.
All the other answers partially address the issue, but could introduce unwanted side effects and non deterministic behaviors.
Have you looked into the PreApplicationStartMethodAttribute?
using System.Web;
[assembly: PreApplicationStartMethod(typeof(ClassLibrary.Startup), "Start")]
namespace ClassLibrary
{
public class Startup
{
public static void Start()
{
// do some awesome stuff here!
}
}
}
More detail: http://dochoffiday.com/professional/simulate-application-start-in-class-library

AssemblyResolve Does not fire

I have an asp.net application. I want to load some assemblies dynamically.
this is my code on application start
protected void Application_Start(Object sender, EventArgs e)
{
LoadPrivateAssemblies();
}
private static void LoadPrivateAssemblies()
{
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomainAssemblyResolve;
Assembly.Load("MyDLL");
}
static Assembly CurrentDomainAssemblyResolve(object sender, ResolveEventArgs args)
{
//loads and returns assembly successfully.
}
this code works fine except when a nested c# code calls a class from my dynamic dll Inside an asp.net page (not code-behind)
sample :
<%if(MyDLL.TestObject.Value){%>white some ting<%}%>
what should I do now ?
I think If I know When a new AppDomain is created, it may solve my problem.
I really think you are barking up the wrong tree here.
Assembly.Load(byte[]) does "persist" the assembly in the app domain - otherwise, what else would it be doing?
To illustrate the fact it does, try this:
Create a solution with one console application, and one class library, named OtherAssembly.
In the class library, OtherAssembly, add a single class:
namespace OtherAssembly
{
public class Class1
{
public string HelloWorld()
{
return "Hello World";
}
}
}
In the console application, use this as your program:
public class Program
{
static void Main(string[] args)
{
try
{
using (var fs = new FileStream("OtherAssembly.dll", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
var buffer = new byte[fs.Length];
// load my assembly into a byte array from disk
fs.Read(buffer, 0, (int) fs.Length);
// load the assembly in the byte array into the current app domain
AppDomain.CurrentDomain.Load(buffer);
}
// get my type from the other assembly that we just loaded
var class1 = Type.GetType("OtherAssembly.Class1, OtherAssembly");
// create an instance of the type
var class1Instance = class1.GetConstructor(Type.EmptyTypes).Invoke(null);
// find and invoke the HelloWorld method.
var hellowWorldMethod = class1.GetMethod("HelloWorld");
Console.WriteLine(hellowWorldMethod.Invoke(class1Instance, null));
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
finally
{
Console.ReadLine();
}
}
}
Don't reference OtherAssembly from your main program assembly, instead, compile the solution and manually drop OtherAssembly.dll in the main program's bin folder.
Run the main program. It outputs "Hello World", which it can only have done if the assembly was loaded and retained in memory. You'll note I've been very careful not to give Visual Studio or C# any hint to load this OtherAssembly. No reference was added, the type is not explicitly referenced in C#.
You need to look again at your problem.
[EDIT: in response to you commenting on the fact this is not an ASP.NET application]
OK - I've moved my main program to an ASP.NET web page and tried accessing the assembly both from code behind and the markup - and it works in both situations. I'm sure you are missing something here - it just doesn't make sense that the behaviour of this method - whose job it is to load an assembly into the current app domain - is different in an ASP.NET scenario.
It seems to me there are at least two things to investigate:
If it really is a new app domain being created on each call, it would only be because of an unhandled exception in your application. The quickest way to diagnose this is to use SysInternals Process Explorer. Fire it up - add .Net -> Total AppDomains to the list of columns and watch the app domain count for your process (IIS worker process or web dev) as you run your app. If this increases on each call, you've got unhandled exceptions tearing down one AppDomain and forcing another to be created.
Are you sure this assembly is really being loaded? When you pass the byte array to Assembly.Load, try also writing it out to disk using FileStream.Write. Open the file in Reflector or some similar tool. Is this the assembly you expected it to be. Is it really being loaded at all, or is it an empty/corrupt array?
I'm not trying to be argumentative, but this really feels like you are looking in the wrong place for the cause of the problem.
I think If I know When a new AppDomain is created, it may solve my problem
You should use AssemblyLoad event. AssemblyResolved occurs when the resolution of assembly is fails
I found that the problem is because Assembly.Load(bytes); does not persist the assembly in appdomain. does any body know how to persist loaded assembly using Assembly.Load(bytes); in appdomain ?
finally I decided to switch to LoadFile method instead of load.
EDIT
Finally I switched from Assemly.Load(byte[]) to Assembly.LoadFile(string).
But it did not correct the problem itself. I have added <%#Assembly name="MyDLL"%> To All of my ASPX files that has markup C# code emebeded.
And This Solved my Problem.
Thanks to your answers. I have voted up answers that helped me, but I can not accept your solutions because no one is not complete enough.

Categories

Resources