How to gracefully unload a child AppDomain that has threads running - c#

I have a service that loads a child AppDomain and then starts a thread running in it. It needs an AppDomain because it dynamically generates and loads some code and I need to be able to restart it without killing the whole service.
So there is a thread running in an event loop in the child AppDomain, it gets events passed to it through a MarshalByRefObject that sticks stuff in a concurrent queue. I want to stop and unload the child AppDomain and create a new one.
I can simply call Unload on the child AppDomain, but that will abort all the threads and throw a ThrearAbortException. How can I gracefully shut it down? If I set some static flag in the child AppDomain using the MarshalByRefObject then how will the main process be able to wait until its done unloading?
I have some example code that kind of shows how its setup and how I can call Unload to kill it, how could I modify this to allow graceful unloading and never have multiple child AppDomains?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security;
using System.Security.Permissions;
using System.Reflection;
using System.Threading;
namespace TestAppDomains
{
/// <summary>
/// Calls to methods magically get transfered to the appdomain it was created in because it derives from MarshalByRefObject
/// </summary>
class MarshalProxy : MarshalByRefObject
{
public AppDomain GetProxyAppDomain()
{
return AppDomain.CurrentDomain;
}
public void SayHello()
{
Console.WriteLine("MarshalProxy in AD: {0}", AppDomain.CurrentDomain.FriendlyName);
}
public void RunLoop()
{
try
{
while (true)
{
Console.WriteLine("RunLoop {0} in {1}", DateTime.Now.ToLongTimeString(), AppDomain.CurrentDomain.FriendlyName);
Thread.Sleep(1000);
}
}
catch(Exception ex)
{
Console.WriteLine("You killed me! {0}", ex);
Thread.Sleep(200); //just to make sure the unload is really blocking until its done unloading
// if the sleep is set to 2000 then you will get a CannotUnloadAppDomainException, Error while unloading appdomain. (Exception from HRESULT: 0x80131015) thrown from the .Unload call
}
}
static int creationCount = 1;
public static MarshalProxy RunInNewthreadAndAppDomain()
{
// Create the AppDomain and MarshalByRefObject
var appDomainSetup = new AppDomainSetup()
{
ApplicationName = "Child AD",
ShadowCopyFiles = "false",
ApplicationBase = Environment.CurrentDirectory,
};
var childAppDomain = AppDomain.CreateDomain(
"Child AD " + creationCount++,
null,
appDomainSetup,
new PermissionSet(PermissionState.Unrestricted));
var proxy = (MarshalProxy)childAppDomain.CreateInstanceAndUnwrap(
typeof(MarshalProxy).Assembly.FullName,
typeof(MarshalProxy).FullName,
false,
BindingFlags.Public | BindingFlags.Instance,
null,
new object[] { },
null,
null);
Thread runnerThread = new Thread(proxy.RunLoop);
runnerThread.Name = "MarshalProxy RunLoop";
runnerThread.IsBackground = false;
runnerThread.Start();
return proxy;
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("I am running in AD: {0}", AppDomain.CurrentDomain.FriendlyName);
var proxy = MarshalProxy.RunInNewthreadAndAppDomain();
proxy.SayHello();
while (true)
{
Console.WriteLine("Press enter to kill and restart proxy");
Console.WriteLine();
Console.ReadLine();
Console.WriteLine("Unloading");
AppDomain.Unload(proxy.GetProxyAppDomain());
Console.WriteLine("Done unloading");
proxy = MarshalProxy.RunInNewthreadAndAppDomain();
}
}
}
}

Try the following
runnerThread.IsBackground = true;
And, yeah, there is no graceful unloading of AppDomain if you didn't stop the threads first.

The situation is essentially the same as if the two AppDomains were separate processes, so you need to use some form of IPC. One option would be to pass an event handle into the child AppDomain when asking the loop to stop. The loop can signal the event before exiting. Wait for the event to give the loop some time to finish. If you time out, then you can do a rough unload.

Serialize all child AppDomains. Send it to remote server. Turn that server off.

Related

C# Mutex always stuck on WaitOne

I have one process that creates the mutex and immediately takes ownership, and then when a button is clicked, it releases it:
Mutex req_mutex = new Mutex(true, "req_mutex");
...
req_mutex.WaitOne(); // not required for first click
req_mutex.ReleaseMutex();
The other process is looping and checking if the mutex exists, when it does it waits for it to be released:
bool waitingForReqMutexCreation = true;
while (waitingForReqMutexCreation)
{
try
{
req_mutex = Mutex.OpenExisting("req_mutex", MutexRights.Synchronize);
waitingForReqMutexCreation = false;
}
catch (WaitHandleCannotBeOpenedException)
{
Thread.Sleep(1000);
}
}
...
req_mutex.WaitOne(); // wait for new request *********** problem here *********
req_mem.readFile(); // read request
req_mutex.ReleaseMutex(); // release req mutex for more requests
the problem is that the WaitOne doesn't continue even after the mutex was supposed to be released by the button in the first process.
Does anyone have an idea why that may be?
I think if you create the mutex with true (new Mutex(true, "req_mutex");)
you so should not need to call WaitOne() in that process.
The documentation says it is better to specify false for initiallyOwned when calling this constructor overload. https://msdn.microsoft.com/en-us/library/f55ddskf(v=vs.110).aspx
EDIT: ahh, you beat me to it :) ...
You are basically acquiring the mutex twice in your first application. You can see this by killing your first application while the second one is running, and you'll get an AbandonedMutexException (which means the Mutex gets acquired). Reproduced with the following, readline instead of button clicks:
namespace Mutex_1
{
class Program
{
static void Main(string[] args)
{
Mutex req_mutex = new Mutex(true, "req_mutex");
String t = string.Empty;
while (!t.Contains("q"))
{
Console.WriteLine("input: ");
t = Console.ReadLine();
Console.WriteLine("waiting for req_mutex");
req_mutex.WaitOne(); // not required for first click
Console.WriteLine("releasing req_mutex");
req_mutex.ReleaseMutex();
}
Console.ReadLine();
}
}
}
namespace Mutex_2
{
class Program
{
static void Main(string[] args)
{
Mutex req_mutex = null;
bool waitingForReqMutexCreation = true;
while (waitingForReqMutexCreation)
{
try
{
req_mutex = Mutex.OpenExisting("req_mutex");
waitingForReqMutexCreation = false;
}
catch (WaitHandleCannotBeOpenedException)
{
Console.WriteLine("req_mutex does not exist.");
Thread.Sleep(1000);
}
}
Console.WriteLine("req_mutex found");
req_mutex.WaitOne(); // wait for new request *********** problem here *********
Console.WriteLine("after req_mutex.WaitOne()");
req_mutex.ReleaseMutex(); // release req mutex for more requests
Console.ReadLine();
}
}
}
More evidence for this statement: calling ReleaseMutex twice in the parent will make things work on the first "click" (and crash the second time). You can fix this without throwing an exception by not acquiring the lock when it is created:
Mutex req_mutex = new Mutex(false, "req_mutex");
I think I found the answer to my own question...
Apparently the amount of WaitOne operations you do does matter.
I took ownership (true argument in the constructor) and did an additional WaitOne in the same thread assuming that it won't hurt.
Now in order to release the mutex I apparently had to call ReleaseMutex twice.
I guess I could still do it like this and call ReleaseMutex in a loop until an exception is thrown...

How to create a generic timeout object for various code blocks?

I have a series of code blocks that are taking too long. I don't need any finesse when it fails. In fact, I want to throw an exception when these blocks take too long, and just fall out through our standard error handling. I would prefer to NOT create methods out of each block (which are the only suggestions I've seen so far), as it would require a major rewrite of the code base.
Here's what I would LIKE to create, if possible.
public void MyMethod( ... )
{
...
using (MyTimeoutObject mto = new MyTimeoutObject(new TimeSpan(0,0,30)))
{
// Everything in here must complete within the timespan
// or mto will throw an exception. When the using block
// disposes of mto, then the timer is disabled and
// disaster is averted.
}
...
}
I've created a simple object to do this using the Timer class. (NOTE for those that like to copy/paste: THIS CODE DOES NOT WORK!!)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Timers;
public class MyTimeoutObject : IDisposable
{
private Timer timer = null;
public MyTimeoutObject (TimeSpan ts)
{
timer = new Timer();
timer.Elapsed += timer_Elapsed;
timer.Interval = ts.TotalMilliseconds;
timer.Start();
}
void timer_Elapsed(object sender, ElapsedEventArgs e)
{
throw new TimeoutException("A code block has timed out.");
}
public void Dispose()
{
if (timer != null)
{
timer.Stop();
}
}
}
It does not work because the System.Timers.Timer class captures, absorbs and ignores any exceptions thrown within, which -- as I've discovered -- defeats my design. Any other way of creating this class/functionality without a total redesign?
This seemed so simple two hours ago, but is causing me much headache.
OK, I've spent some time on this one and I think I have a solution that will work for you without having to change your code all that much.
The following is how you would use the Timebox class that I created.
public void MyMethod( ... ) {
// some stuff
// instead of this
// using(...){ /* your code here */ }
// you can use this
var timebox = new Timebox(TimeSpan.FromSeconds(1));
timebox.Execute(() =>
{
/* your code here */
});
// some more stuff
}
Here's how Timebox works.
A Timebox object is created with a given Timespan
When Execute is called, the Timebox creates a child AppDomain to hold a TimeboxRuntime object reference, and returns a proxy to it
The TimeboxRuntime object in the child AppDomain takes an Action as input to execute within the child domain
Timebox then creates a task to call the TimeboxRuntime proxy
The task is started (and the action execution starts), and the "main" thread waits for for as long as the given TimeSpan
After the given TimeSpan (or when the task completes), the child AppDomain is unloaded whether the Action was completed or not.
A TimeoutException is thrown if action times out, otherwise if action throws an exception, it is caught by the child AppDomain and returned for the calling AppDomain to throw
A downside is that your program will need elevated enough permissions to create an AppDomain.
Here is a sample program which demonstrates how it works (I believe you can copy-paste this, if you include the correct usings). I also created this gist if you are interested.
public class Program
{
public static void Main()
{
try
{
var timebox = new Timebox(TimeSpan.FromSeconds(1));
timebox.Execute(() =>
{
// do your thing
for (var i = 0; i < 1000; i++)
{
Console.WriteLine(i);
}
});
Console.WriteLine("Didn't Time Out");
}
catch (TimeoutException e)
{
Console.WriteLine("Timed Out");
// handle it
}
catch(Exception e)
{
Console.WriteLine("Another exception was thrown in your timeboxed function");
// handle it
}
Console.WriteLine("Program Finished");
Console.ReadLine();
}
}
public class Timebox
{
private readonly TimeSpan _ts;
public Timebox(TimeSpan ts)
{
_ts = ts;
}
public void Execute(Action func)
{
AppDomain childDomain = null;
try
{
// Construct and initialize settings for a second AppDomain. Perhaps some of
// this is unnecessary but perhaps not.
var domainSetup = new AppDomainSetup()
{
ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase,
ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile,
ApplicationName = AppDomain.CurrentDomain.SetupInformation.ApplicationName,
LoaderOptimization = LoaderOptimization.MultiDomainHost
};
// Create the child AppDomain
childDomain = AppDomain.CreateDomain("Timebox Domain", null, domainSetup);
// Create an instance of the timebox runtime child AppDomain
var timeboxRuntime = (ITimeboxRuntime)childDomain.CreateInstanceAndUnwrap(
typeof(TimeboxRuntime).Assembly.FullName, typeof(TimeboxRuntime).FullName);
// Start the runtime, by passing it the function we're timboxing
Exception ex = null;
var timeoutOccurred = true;
var task = new Task(() =>
{
ex = timeboxRuntime.Run(func);
timeoutOccurred = false;
});
// start task, and wait for the alloted timespan. If the method doesn't finish
// by then, then we kill the childDomain and throw a TimeoutException
task.Start();
task.Wait(_ts);
// if the timeout occurred then we throw the exception for the caller to handle.
if(timeoutOccurred)
{
throw new TimeoutException("The child domain timed out");
}
// If no timeout occurred, then throw whatever exception was thrown
// by our child AppDomain, so that calling code "sees" the exception
// thrown by the code that it passes in.
if(ex != null)
{
throw ex;
}
}
finally
{
// kill the child domain whether or not the function has completed
if(childDomain != null) AppDomain.Unload(childDomain);
}
}
// don't strictly need this, but I prefer having an interface point to the proxy
private interface ITimeboxRuntime
{
Exception Run(Action action);
}
// Need to derive from MarshalByRefObject... proxy is returned across AppDomain boundary.
private class TimeboxRuntime : MarshalByRefObject, ITimeboxRuntime
{
public Exception Run(Action action)
{
try
{
// Nike: just do it!
action();
}
catch(Exception e)
{
// return the exception to be thrown in the calling AppDomain
return e;
}
return null;
}
}
}
EDIT:
The reason I went with an AppDomain instead of Threads or Tasks only, is because there is no bullet proof way for terminating Threads or Tasks for arbitrary code [1][2][3]. An AppDomain, for your requirements, seemed like the best approach to me.
Here's an async implementation of timeouts:
...
private readonly semaphore = new SemaphoreSlim(1,1);
...
// total time allowed here is 100ms
var tokenSource = new CancellationTokenSource(100);
try{
await WorkMethod(parameters, tokenSource.Token); // work
} catch (OperationCancelledException ocx){
// gracefully handle cancellations:
label.Text = "Operation timed out";
}
...
public async Task WorkMethod(object prm, CancellationToken ct){
try{
await sem.WaitAsync(ct); // equivalent to lock(object){...}
// synchronized work,
// call tokenSource.Token.ThrowIfCancellationRequested() or
// check tokenSource.IsCancellationRequested in long-running blocks
// and pass ct to other tasks, such as async HTTP or stream operations
} finally {
sem.Release();
}
}
NOT that I advise it, but you could pass the tokenSource instead of its Token into WorkMethod and periodically do tokenSource.CancelAfter(200) to add more time if you're certain you're not at a spot that can be dead-locked (waiting on an HTTP call) but I think that would be an esoteric approach to multithreading.
Instead your threads should be as fast as possible (minimum IO) and one thread can serialize the resources (producer) while others process a queue (consumers) if you need to deal with IO multithreading (say file compression, downloads etc) and avoid deadlock possibility altogether.
I really liked the visual idea of a using statement. However, that is not a viable solution. Why? Well, a sub-thread (the object/thread/timer within the using statement) cannot disrupt the main thread and inject an exception, thus causing it to stop what it was doing and jump to the nearest try/catch. That's what it all boils down to. The more I sat and worked with this, the more that came to light.
In short, it can't be done the way I wanted to do it.
However, I've taken Pieter's approach and mangled my code a bit. It does introduce some readability issues, but I've tried to mitigate them with comments and such.
public void MyMethod( ... )
{
...
// Placeholder for thread to kill if the action times out.
Thread threadToKill = null;
Action wrappedAction = () =>
{
// Take note of the action's thread. We may need to kill it later.
threadToKill = Thread.CurrentThread;
...
/* DO STUFF HERE */
...
};
// Now, execute the action. We'll deal with the action timeouts below.
IAsyncResult result = wrappedAction.BeginInvoke(null, null);
// Set the timeout to 10 minutes.
if (result.AsyncWaitHandle.WaitOne(10 * 60 * 1000))
{
// Everything was successful. Just clean up the invoke and get out.
wrappedAction.EndInvoke(result);
}
else
{
// We have timed out. We need to abort the thread!!
// Don't let it continue to try to do work. Something may be stuck.
threadToKill.Abort();
throw new TimeoutException("This code block timed out");
}
...
}
Since I'm doing this in three or four places per major section, this does get harder to read over. However, it works quite well.

how to get PID of my app at runtime using C#

My app checks at startup if any other instance of the same is running already, if yes then it will close all other instances. For this I tried using Process.GetProcessByName("AppName") function and store all the process with AppName in processes[] array. Now i want to find the PID of current instance so that i can close all other instances of my app (which obviously have same name but different PIDs). But i am unable to find that even after lot of googling. Also how can i find the PID of an instance of my app which i have created with Process.Start("AppName.exe") function called from inside AppName.exe
OK, given problems with my other solution, see the following
In order to hook in between processes, you need some form of IPC. To use the simplicty of shared handles between EventWaitHandles, you could make each program listen for a cancellation flag.
public static EventWaitHAndle CancellationEvent =
new EventWaitHandle(
false,
EventResetMode.AutoReset,
"MyAppCancel");
private object lockObject = new object();
And later...
Task.Run(() =>
{
while(true)
{
CancellationEvent.WaitOne();
lock(lockObject)
if(!thisIsCalling) // static bool to prevent this program from ending itself
Environment.Exit(0);
}
}
And then call the cancellation like so
lock(lockObject)
{
thisIsCalling = true;
CancellationEvent.Set();
thisIsCalling = false;
}
Why don't you just check equality with your current process?
var processes = Process.GetProcessByName("AppName");
foreach (var p in processes)
{
if (p != Process.GetCurrentProcess())
p.CloseMainWindow();
}
If you're interested in closing other instances of your app, why not do the opposite and prevent multiple instances from opening in the first place? Using EventWaitHandle can do this thusly:
bool created;
var eve = new System.Threading.EventWaitHandle(
false,
EventResetMode.AutoReset,
"MyAppHandle",
out created);
if(!created)
{
eve.Set();
Environment.Exit(-1); // Always use an exit error code if you're expecting to call from the console!
}
The handle parameter, "MyAppHandle" in this case, will be shared across the entire system, thus meaning not only will the out created paramete be false on secondary instaces, but you can use eve.Set() to cause the handle to fire acorss application. Set up a listening thread and this can allow a message loop to display a message when you attempt to open second instance.
Task.Run(() =>
{
while(true)
{
eve.WaitOne();
// Display an error here
}
}

Windows service status stays at starting for ever even when it has actually started

I followed the instructions in the marked answer here to create a service. The service gets installed correctly. When I start the service after a while it throws a message
"Windows could not start the xxx service on Local Computer.
Error 1053: The service did not respond to the start or control request in a timely fashion.
"
After I click ok, its status stays at "Starting" for ever. When I checked the application and system logs, there were no errors.
When I check the SQL trace, the service is actually running correctly and doing what its supposed to do. So why does its status stay at "Starting" ?
Update:
This is the code in OnStart method
protected override void OnStart(string[] args)
{
Loader loader = new Loader();
loader.StartProcess();
}
Update 2:
based on WiktorZychla's comment I did this and it worked :)
protected override void OnStart(string[] args)
{
Loader loader = new Loader();
ThreadStart threadDelegate = new ThreadStart(loader.StartProcess);
Thread newThread = new Thread(threadDelegate);
newThread.Start();
}
Based on WiktorZychla's comment this is what I did
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using IndexLoader;
using System.Threading;
namespace myNameSpace
{
public partial class LoaderService : ServiceBase
{
Thread newThread;
public LoaderService()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
Loader loader = new Loader();
ThreadStart threadDelegate = new ThreadStart(loader.StartProcess);
newThread = new Thread(threadDelegate);
newThread.Start();
}
protected override void OnStop()
{
if ((newThread != null) && (newThread.IsAlive))
{
Thread.Sleep(5000);
newThread.Abort();
}
}
}
}
It would be instructive to know exactly what is in your OnStart() method. The OnStart() method is a callback from the OS that is used to start your service, but it must return within 30 seconds or so (I remember reading that somewhere). Otherwise, the OS gives the message you're seeing. In short, limit the OnStart() method to getting things initialized, and defer the actual work your service is to perform to a thread of some kind.
In your Program.cs file in the Main() function make sure that you have:
ServiceBase.Run(new ServiceClassHere());
I've been guilty many times when creating a windows form app of keeping
Application.Run(new Class()); in my Main() function

why does Mutex.WaitOne() returns immediately in WPF?

I am trying to implement SigleInstance application per user session. I am using a local mutex for this. I have the following startup code.
public partial class App : Application
{
private const string applicationName = "EDisc.Client.Application";
private const string appGUID = "2AE55EA7-B392-42EF-BDFA-3DAFCE2B4B32";
public App()
{
bool isUnique = false;
using (var mutex = new Mutex(false, appGUID)) //Local mutex is local to the machine,it is per user,If u need a instance per machine,prefix appGUID with global.
{
try
{
try
{
isUnique = mutex.WaitOne(TimeSpan.FromSeconds(3), true); //wait in case first instance is shutting down.
if (isUnique) //If this is the first process.
{
this.Navigated += new NavigatedEventHandler(App_Navigated);
this.Exit += new ExitEventHandler(App_Exit);
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
this.DispatcherUnhandledException += new System.Windows.Threading.DispatcherUnhandledExceptionEventHandler(App_DispatcherUnhandledException);
}
else //If process is already running.
{
LoggingHelper.LogMessage(CommonMessages.ANOTHER_APP_INSTANCE_OPEN, Source.EDiscClientApplication);
MessageBox.Show(CommonMessages.CLOSE_OTHER_APP_INSTANCE, CommonMessages.ANOTHER_APP_INSTANCE_OPEN,
MessageBoxButton.OK,
MessageBoxImage.Exclamation);
CloseApplicationInstance();
return;
}
}
catch (AbandonedMutexException)
{
}
}
finally
{
if (isUnique)
mutex.ReleaseMutex();
}
}
}
}
isUnique is always true irrespective of whether it is the first instance or second instance. mutex.waitone() returns immediately without waiting. I have been scratting my head for what can possibly be wrong in this code. Please help
Your code is releasing the mutex at the end of the App constructor - you keep it acquired only for a few microseconds (while registering those event handlers). You'll have to move the ReleaseMutex() call (and also the Dispose() call done by the using statement) to run at shutdown of your application.
I believe what is happening is that you are releasing the mutex in the finally block of the construtor. When the constructor exits, you are releasing the mutex and hence the next instance of the application can also aquire this mutex.
You can alternatively try:
public Mutex(
bool initiallyOwned,
string name,
out bool createdNew
)
So you check the out parameter which would return false if the mutex has already been created by another process

Categories

Resources