Process.HasExited race condition - c#

I have an instance of System.Diagnostics.Process which was created via Process.GetProcessesByName.
After I sucessfully open the process, I perform various operations, such as reading its memory and the window title.
This operations are constantly executed based on a timer, by which I mean the Timer.Elapsed event handler is the source of the process operations.
Now, I noticed that I have a race condition that I've been unable to solve using anything I know. Here is how it happens:
timerElapsedEvent(...) {
if (!process.HasExited) {
process.Refresh(); // Update title.
var title = process.MainWindowTitle;
}
}
If the process is running, and my code enters the if block, there is a small chance the process might exit before the process.MainWindowTitle call is executed, which would cause an exception.
What I need is a way to somehow capture the exit event of the process and keep it alive untill it is safe to close it without crashing my application which is monitoring it, thus making sure it will wait for process.MainWindowTitle before closing (or any other solution that would solve this problem).
Moreover, at the same time, another method might be running a ReadProcessMemory, which would crash too.
How can I solve this?
PS: Process.Exit event handler doesn't work because it won't be fired before process.MainWindowTitle, it will only be fired after the current instruction is finished.
I'm pretty sure that somehow controlling the exit event is the only way to solve this because the HasExit could change at any time, doesn't mather how many checks I have before actually calling a method on the process.
PS2: I just realized this is a TOCTTOU case, which is unsolvable unless I can control the process I opened, so I'm leaving this here just to see if anyone knows a way to do that.

Short version: you can't.
There is a fundamental "time-of-check-to-time-of-use" issue here that you don't have enough control over to solve. The OS is always able to kill the process you are dealing with (either arbitrarily, or due to some failure in the process), between the time you check the HasExited property and the time you check the MainWindowTitle property.
The Process class doesn't do much to enforce getting the exception, but it does enough. In particular, calling Refresh() forces the class to "forget" anything it knows about the process, so that it will re-retrieve the information when you ask for it again. This includes the main window handle for the process.
The Process class uses the native window enumeration functions to search for the window handle for the known process ID. Since the process has exited, it fails to find the handle, returning a NULL value (IntPtr.Zero in managed terms). On seeing the null return value, the Process class forces the InvalidOperationException to be called.
The only reliable solution is to always be prepared to catch the exception. There will always be a chance that between checking for the state and trying to do something that relies on it, that state can change.
While academic, I find it interesting to note that if you set the EnableRaisingEvents property, the Process class can be (and usually is) even more efficient about detecting the exited process and throwing the exception.
In particular, when the EnableRaisingEvents property is set, the Process class registers to be notified by the OS (via the thread pool's RegisterWaitForSingleObject() method) when the process handle is signaled. I.e. the Process class does not even need to go through the effort of searching for the main window handle in this case, because it's notified almost instantly if the process exits.
(Of course, there's still potentially an internal race condition, in a very tiny window of opportunity, since the notification may not have arrived yet when the Process class checks for the has-exited state, but the process may still have exited before the Process class enumerates the windows).
Anyway, this last bit doesn't affect the basic answer; it's just a bit of trivia I learned and found interesting while wandering through the Process source code. :)

Related

C# how should I go about creating this threading application?

Alright I will attempt to explain every aspect of why I need to do this a certain way. Basically, I need an application to execute a certain .exe multiple times asynchronously.
Specs:
I need to be able to restrict the amount of executions going at one time.
It has to use threading because my program has a GUI and simply launching the .exe's and monitoring them will lock up the .GUI AND the console for other things.
How should I go about doing this? (examples help me a lot)
I've already told you multiple times how you should go about this. The launcher program has a single thread. It monitors the child processes. If a process ends and there is a free processor, it starts up a new process and affinitizes the process to that processor. When it's not doing any of those things it yields control back to its UI. Since each of those operations is of short duration, the UI never appears to block.
UPDATE
Actually this wasn't a great answer. As Henk pointed out in my comments, when you call Process.Start() that's not a blocking call. You have to explicitly set Process.EnableRaisingEvents to true, and handle the Exited event. I'm not sure if the Exited event is fired in the calling thread (I doubt it, but you should check), but the point is starting a process isn't a blocking call, so you don't need more threads doing the waiting.
See this similar answer for more details: Async process start and wait for it to finish
PREVIOUS ANSWER
Fire off your threads (limited to your max number of threads), and have them run the external exe using the Process.Start() method. Make sure you set them to wait for the process to finish. When the processes finish, have the threads use something like Interlocked.Increment() to increment a counter variable that you can read from your main form code. Better still, have those threads call a callback delegate (e.g. Action<T>), which will in turn check for this.InvokeRequired before doing the actual work.

How to detect when main thread terminates?

What I need to know:
I would like to detect when a the main thread (process?) terminates so that I can ensure certain actions are performed before it is terminated.
What I have found myself:
I found the events AppDomain.DomainUnload and AppDomain.ProcessExit. AppDomain.DomainUnload seems to work with non-applications like MbUnit. AppDomain.ProcessExit seems to work with applications but there is a 3 second time limit which I really don't like. Is there more ways to detect when an AppDomain / process terminates?
Background:
I am looking for such an event to ensure my log is persistet to file when the application terminates. The actual logging runs on another thread using a producer-consumer pattern where it is very likely that log entries might queue up in memory and I need to ensure this queue is saved to file when the application terminates.
Is there anything else I should be aware of?
Update:
Changed the above to reflect what I have found out myself. I am not happy with the 3 second time limit during ProcessExit. The MSDN documentation does say though that it can be extended:
The total execution time of all
ProcessExit event handlers is limited,
just as the total execution time of
all finalizers is limited at process
shutdown. The default is three
seconds, which can be overridden by an
unmanaged host.
Does anyone know how to override the default?
More ideas are also highly appreciated!
Follow up:
I have posted a follow up question to this.
You should have an entry point for your application. Normally you can do there some logging when all tasks are terminated:
static void Main()
{
try
{
Application.Run( .... );
}
finally
{
// logging ...
}
}
What exactly do you want to find out?
When the process terminates? (Just because the AppDomain is unloaded doesn't necessarily mean that the entire process is terminating)
When the main thread terminates (If there are other non-background threads, the main thread can terminate without the process terminating (or AppDomain unloading)
So they're not quite the same thing.
Anyway, it is generally dangerous to have log messages buffered in memory at all. What happens if someone turns off the power? Or if I terminate your process through Task Manager? All your log messages are gone. So often, you'll want unbuffered writes in your log, to get messages pushed to disk immediately.
Anyway, another (more robust) approach might be to run the logger itself in a non-background thread. That way, even if the rest of the application terminates, the logger won't, so the process is kept alive. Then you just have to set some flag when the rest of the app terminates, to let the logger know that it too should close once it has written out all pending log messages.
It still won't save you from the case where the system loses power or someone forcibly termianates the process on the OS-level, but it will handle all cases where the application closes normally, and gives you unlimited time to perform clean-up actions (since the process isn't actually terminating yet, it's still got one live thread)
ie. guaranteed to be called and have unlimited time to finish?
Unfortunately, NO option is going to have unlimited time, and be guaranteed. There is no way to enforce this, as many things can happen. Somebody tripping over the power cord or a forced termination of your program will prevent any option from giving you adequate time to handle things.
In general, putting your logic at the end of the Main routine is probably the most reasonable option, since that gives you complete freedom in handling your termination events. You have no time constraints there, and can have the processing take as much time as needed.
There are no guarantees that this will run, though, since a forceful termination of your program may bypass this entirely.
Based on the documentation, it looks like the default application domain (the one your Main method is probably running in) will not receive the DomainUnload event.
I don't know a built-in event that would do what you expect.
You could define your own custom event, have interested parties register with it, and fire off the event just before you return from Main().
I don't know how old this thread is, but I've had a similar problem whcih was a little tough for me to solve.
I had a WinForms application that was not firing any of the above forementioned events when a user logged out. Wraaping the Application.Run() in a try finally didn't work either.
Now to get around this you would have to using PInvoke into Win32 API's to achieve this. Well you did prior to .NET 2.0 anyways. Luckly MS introduced a new class called SystemEvents. With this class you can catch a SessionEnd event. This event allows you to cleanup when the OS want to terminate your app. There is no .NET time limit o this event it appears, although the OS will eventually kill your app if you take too long. This is a little more than 3 seconds, although 3 seconds should be plenty of time to cleanup.
Secondly my other problem was I wanted my worker thread to terminate the main thread once it was finished its work. With an Application.Run() this was hard to achieve. What I ended up doing was calling Application.Run() with a shared Application context. The thread is then able to call ApplicationContext.ThreadExit() to force the Application.Run to return. This seems to work quite nicely.
Hope this helps someone.
Regards
NozFX

how to track if a given process throws exception, using windows service in C#

My process sometimes throws exception like dllnotfound after start. i have a monitor service responsible for maintaining the consistent state of the process.
how can i keep track of state of my process using windows service.
is there an open source implementation of windows service that maintains/track the state of process in windows.
That's not possible, exceptions are local to a thread first, local to a process secondary if it is unhandled. An unhandled exception will terminate the process. The only shrapnel you could pick up from such a dead process is the process exit code. Which should be set to 0xe0434f4e, the exception code for an unmanaged exception. No other relevant info is available, unless there's an unhandled exception handler in the process that logs state. That state is very unreliable, the process suffered a major heart attack.
Keeping multiple processes in synch and running properly when they may die from exceptions is extraordinarily difficult. Only death can be detect reliably, avoid doing more.
Edit: So the actual problem wasn't that the process was dying, but that the process was stuck in an exception handler dialog waiting for the user to hit debug or cancel. The solution to the problem was to disable the .net JIT debug dialog, instructions here
http://weblogs.asp.net/fmarguerie/archive/2004/08/27/how-to-turn-off-disable-the-net-jit-debugging-dialog.aspx
My original proposed solution is below
Not a window service, but this is a pretty easy .NET program to write.
use System.Diagnostics.Process to get a Process object for the process you want to check. You can use GetProcessByName if you want to open an existing process. If you create the process from C#, then you will already have the process object.
Then you just can WaitForExit either with or without a timeout on the Process object. or test the HasExited property, or register an Exited callback. Once the process has exited, you can check the ExitCode property to find out whether the process returned an error value.
Have your process write events and exceptions to the system's application log and have your monitor check for entries periodically to find events relating to your process, and you can check the system events for service start and stop events.
If the process itself is a windows service, you can check its status using the `System.ServiceProcess.ServiceController'.
this worked for now
http://weblogs.asp.net/fmarguerie/archive/2004/08/27/how-to-turn-off-disable-the-net-jit-debugging-dialog.aspx
In the case of DllNotFoundException and other things that happen at startup, you can have the application indicate when it's finished starting up. Have it write a timestamp to a file, for instance. Your monitor can compare the time the application started with the time in the file.
One thing you could do is to monitor the CPU usage of the process. I am assuming your process goes away when the exception is thrown. Therefore, the CPU usage of the process should be 0 since it is no longer available. Therefore, if the CPU usage stays at zero for a certain period of time, you can safely assume that the process has raised the exception. This method is not fool proof since you are basing your decision on CPU usage and a legitimate process may have a zero CPU usage for a given period of time. You can incorporate this check inside your monitoring service or you could write a simple VB script to check process CPU usage externally.

Creating a cancel scheme

I have a program that will analyzes source code. It can recursively go through a directory to find all projects, and then recursively go through the project to find all source code.
I want to create a cancel process button, which allows the user to stop the code parsing. I run the code parsing in a background worker. I want to be able to watch for the cancel event.
The problem is figuring out how to edit my code so that it will go and check that item and return back to the GUI. The parsing process goes several methods deep.
In a much smaller process, I successfully use a thread-safe singleton that has a bool that says whether or not a cancel has been requested, and stop the loop where it is running.
What would be the best way of working this cancel request into my code?
EDIT: Here is an idea, inspired by John Saunders' answer.
What if I run a background thread in my processing thread that watches for the Cancel Singleton to change, and then throw an exception from that process? Does this seem like good practice? This does not work as intended
EDIT 2: John Saunders' answer seems to be the best for now. I will just throw my own exception when the Singleton is true for now. I'll wait to see if any other solutions are proposed
Thread.Abort is a bad idea, as it interrupts the thread at an arbitrary point - probably interrupts it where you'd least like to be interrupted.
Set a flag that it seen by the thread being cancelled. Check it at the beginning of each operation. The idea would be to identify places in the code where it is safe to stop, and to check the flag at only those points.
You may find it useful to throw an exception at those points. The exception should be one that is not caught by your code until it reaches the boundary between your code and the UI. At that point, your code would simply return.
You could use the Thread.Abort() function on your background worker thread. This throws a ThreadAbortException which you can catch in any of your methods but which will atomatically be rethrown at the end of the catch blocks.
Also all finally-blocks will be executed.
It sounds like you're using the .NET backgroundworker class. I think you can pass a object parameter into the RunWorkerAsync method which then becomes accessible to the background thread in the DoWork event handler argument.
You could then modify that object in the UI thread (for example update a boolean cancel property) and periodically check on it from your background process.
There are various ways to perform a cancel on threaded operations; all of which involve the periodic checking of a flag or other value to determine if the thread should continue operating or not.
I would not recommend throwing exceptions for this feature. First of all, cancelling is not an exceptional circumstance, and second, it's overkill for what you're trying to implement.
Instead, you could use a simple, thread-safe boolean flag as a static member of a class accessible from any thread, or use a synchronization object such as a named Mutex. Signalling the synchronization object would then allow the thread to know it must cancel.

System.Diagnostics.Process.Start weird behaviour

I'm writing an application to start and monitor other applications in C#. I'm using the System.Diagnostics.Process class to start applications and then monitor the applications using the Process.Responding property to poll the state of the application every 100 milisecs. I use Process.CloseMainWindow to stop the application or Process.Kill to kill it if it's not responding.
I've noticed a weird behaviour where sometimes the process object gets into a state where the responding property always returns true even when the underlying process hangs in a loop and where it doesn't respond to CloseMainWindow.
One way to reproduce it is to poll the Responding property right after starting the process instance. So for example
_process.Start();
bool responding = _process.Responding;
will reproduce the error state while
_process.Start();
Thread.Sleep(1000);
bool responding = _process.Responding;
will work.
Reducing the sleep period to 500 will introduce the error state again.
Something in calling _process.Responding too fast after starting seems to prevent the object from getting the right windows message queue handler. I guess I need to wait for _process.Start to finish doing it's asynchronous work. Is there a better way to wait for this than calling Thread.Sleep ? I'm not too confident that the 1000 ms will always be enough.
Now, I need to check this out later, but I am sure there is a method that tells the thread to wait until it is ready for input. Are you monitoring GUI processes only?
Isn't Process.WaitForInputIdle of any help to you? Or am I missing the point? :)
Update
Following a chit-chat on Twitter (or tweet-tweet?) with Mendelt I thought I should update my answer so the community is fully aware..
WaitForInputIdle will only work on applications that have a GUI.
You specify the time to wait, and the method returns a bool if the process reaches an idle state within that time frame, you can obviously use this to loop if required, or handle as appropriate.
Hope that helps :)
I think it may be better to enhance the check for _process.Responding so that you only try to stop/kill the process if the Responding property returns false for more than 5 seconds (for example).
I think you may find that quite often, applications may be "not responding" for a split second whilst they are doing more intensive processing.
I believe a more lenient approach will work better, allowing a process to be "not responding" for a short amount of time, only taking action if it is repeatedly "not responding" for several seconds (or however long you want).
Further note: The Microsoft documentation indicates that the Responding property specifically relates to the user interface, which is why a newly started process may not have it's UI responding immediately.
Thanks for the answers. This
_process.Start();
_process.WaitForInputIdle();
Seems to solve the problem. It's still strange because Responding and WaitForInputIdle should both be using the same win32 api call under the covers.
Some more background info
GUI applications have a main window with a message queue. Responding and WaitForInputIdle work by checking if the process still processes messages from this message queue. This is why they only work with GUI apps. Somehow it seems that calling Responding too fast interferes with getting the Process getting a handle to that message queue. Calling WaitForInputIdle seems to solve that problem.
I'll have to dive into reflector to see if I can make sense of this.
update
It seems that retrieving the window handle associated with the process just after starting is enough to trigger the weird behaviour. Like this:
_process.Start();
IntPtr mainWindow = _process.MainWindowHandle;
I checked with Reflector and this is what Responding does under the covers. It seems that if you get the MainWindowHandle too soon you get the wrong one and it uses this wrong handle it for the rest of the lifetime of the process or until you call Refresh();
update
Calling WaitForInputIdle() only solves the problem some of the time. Calling Refresh() everytime you read the Responding property seems to work better.
I too noticed that in a project about 2 years ago. I called .Refresh() before requesting certain prop values. IT was a trial-and-error approach to find when I needed to call .Refresh().

Categories

Resources