I wrote a C# NET application (Console app that is run as a Service) that manages a Java process (Minecraft Game Server), and our Web Panel software manages my application. When the Java process stops, my application stops itself, and when my application stops, it stops the Java process.
The issue I am running into is that I deployed the software to all of our machines after extensive bug testing, but there seems to be a bug we missed where it is NOT shutting down the Java process sometimes. This bug is horrible as the Web Software tries to start my application, my application tries to start the Java process, but fails due to it being unable to IP bind (since the old process stayed open) and we wind up with 15-30 bugged Java processes running.
I am using CurrentDomain_UnhandledException to catch my application's crashes and call TerminateProcess().
I am using CtrlTypes.CTRL_C_EVENT and CtrlTypes.CTRL_CLOSE_EVENT to detect my application being closed which also calls the TerminateProcess() function.
I have tried both of the following methods...
static void TerminateProcess()
{
log.LogMessage("Minecraft Process Shutdown.");
SendProcessCmd("stop");
}
and
static void TerminateProcess()
{
log.LogMessage("Minecraft Process Shutdown.");
minecraftProcess.Kill();
}
However, I seem to be missing another way that my C# application is being shut down, because both ways seem to leave a Java process running every once in a while that I can't reproduce locally.
Well, you did not state any question, I’m going to guess you wanted to ask for other ways a process can get shut down, so that you can intercept it and ensure the Java process termination. Simply said: That is impossible (in full generality).
Just look at your own code: You are doing exactly the same thing to Minecraft: Calling TerminateProcess causes the target process to terminate immediately, without any chance to clean up. Should anyone call TerminateProcess on you (e.g. a user killing the process from Task Manager), your process just terminates immediately.
Also, some fatal exceptions are uncatchable, e.g. when your process dies on a stack overflow, you are not told, just terminated.
I guess you’d need to create another process, watching over your process… (Or rethink the whole architecture, creating and killing processes, especially with TerminateProcess, seems a bit rough to me.)
Related
I've developed a program (winforms application, not a service) in C# that runs on a windows server.
The program starts multiple times based on requests from outside the server.
From time to time I see that the program is "Suspended" for an unknown reason. I think it is related to a lack of resources, but not sure.
How can I prevent windows from suspending my program?
Update
To be clear, I know that the program crash and it is OK. What I'm asking is not how to improve performance \ prevent the crash, but how to remove the process from the process list \ prevent this suspended status?
Depends in your hardware/software configuration, it's hard to know where is your bottleneck.
I recommend instead to do Multi-thread/task app where you're able to control threads and asign priority, resources, stop, resume, abort, etc...
use on command console to start and check if happends the same but with the parameter high:
start /HIGH <ProgramPath>
Read more how to change priority on executables
Task Scheduler on windows servers MSDN -> Priority
(It's only an opinion, start digging about others solutions.)
You must set the ServiceBase.CanPauseAndContinue Property to False in the constructor of the service before it is started.
NOTE the side effect is:
If CanPauseAndContinue is false, the SCM will not pass Pause or
Continue requests to the service, so the OnPause and OnContinue
methods will not be called even if they are implemented. In the SCM,
the Pause and Continue controls are disabled when CanPauseAndContinue
is false.
For more information see this Microsoft Doc
There are multiple methods of keeping an app awake.
One method would be to request a deferral and then only mark that deferral complete when you are done.
First you need a deferral object that will remain in scope of your process
SuspendingDeferral deferral
Then you need to override OnSuspending
async protected void OnSuspending(object sender, SuspendingEventArgs args)
{
deferral = args.SuspendingOperation.GetDeferral();
await SuspensionManager.SaveAsync();
}
Then you need to mark the deferral complete when your process is done doing whatever it was doing
if (deferral is not null) { deferral.Complete(); }
Full details can be found in the Microsoft docs
For discussion of other methods see this thread:
How to Disable UWP App Suspension?
Technically the process is suspended but if you look at the memory consumption of 32K you can tell it was not suspended. Your process did crash with an unhandled exception which in turn triggers Windows Error Reporting to take a memory dump.
This involves some kernel magic which keeps a process handle in the kernel (System process) alive. It is not a big deal or memory leak since the process did already terminate. Only the PEB (Process Environment Block) the 32K which includes mostly command line, loaded dlls and environment variables are still there.
I would not worry about suspended processes but why your process did crash with an unhandled exception. This could even be a feature to make programers aware that their process did crash by looking at a looong list of suspended processes in Task Manager ;-).
Since it is a .NET Application you will find a generic error messages that a process did crash in the Application event log and a .NET Runtime logged error message with more exception details.
Perhaps that is already enough to keep you going to fix your issue. If not you can configure WER to create a full memory dump via a registry setting (https://learn.microsoft.com/en-us/windows/win32/wer/collecting-user-mode-dumps). Now you have for each "suspended" process a full memory dump you can load into Visual Studio to look further what was the issue.
To further check who holds your process handle still open you can use handle e.g. ProcessHacker (the better Process Explorer) https://processhacker.sourceforge.io/nightly.php
If something else is happening you can see with this tool who is holding any outstanding handles to your process open. But I strongly suspect it is the Windows Kernel.
I use the c# process class to open a separate application that has no GUI. it is s a c++ project that I use the Process.Kill() on to end it. The problem is this doesn't give it a chance to finish its actions. Process.Close() just releases the object in my main app and and leaves the separate application running.
Whats the best way to make this process close gracefully?
In the past I needed to start a non-gui C# tool from a GUI C# tool, both of which I had written. I used the standard input/output streams to communicate between both tools.
You could make your C++ tool listen on its stdin for a command that indicates the tool should quit gracefully. Then, in your C# application, send the quit command, wait for a reasonable amount of time and if the tool hasn't ended by then, kill it.
I'm sorry that my C++ is not good enough to give you an example for the C++ side, but the following lines are used in my C# project to tell the external process to end:
m_consoleProcess.StandardInput.WriteLine("QUIT");
m_consoleProcess.WaitForExit(10000);
if (!m_consoleProcess.HasExited)
{
m_consoleProcess.Kill();
}
If you need to manage separate external processes, of course you need to store one Process instance for each of them and you have to handle the case that the external process was ended before your application should quit.
I have a program I need to run before a system shutdown executes. This means, before any program gets terminated because of the shutdown, I need to execute said program, ideally via Process.Start().
Initially I tried executing said program in the Windows Shutdown Scripts, however that script is only executed after programs have already been terminated. I however need to terminate some running applications in the right order.
I have tried the event SystemEvents.SessionEnding and SessionEnded, but this event does not let you wait for more than 1-2 seconds, and the cancelling of the shutdown is not possible either.
I got up to this example where, in the WndProc event about shutdown I would execute a Process. I reach the Event, I reach the point where I can actually pause the shutdown process. However, when I try to actually call a process, I get the "0xC0000142" error.
A search for this resulted in one option being that the user is incorrect, however I want to call this application with the user that is running the executing program. The other option was that the environment path was wrong. I set an environment path for the second option, but in my opinion, I shouldn't need to change anything for the first option, since I want to execute it with the current user.
A third possibility I thought about might be that at this state of the system shutdown, no new processes can be spawned.
What can I do to fix this and actually execute the program here? I seem to be out of ideas at this point.
Clarification:
The "cleanup" program needs to shut down programs in a given order. The programs to be shut down are our own, but Windows Forms (the only way I can see that can use a shutdown handler) cannot be used there.
Program A is the one that handles the OnShutdown. Program A, on Shutdown, will call Program B, which does the ordered closing of programs. Program B, in my solution (that includes Forms) cannot be launched and returns an error, as specified in paragraph 4. The only user interaction here would be a user pressing a power button leading to system shutdown, or a remotely executed "shutdown.exe" call.
I have an application that I am writting that communicates with a third-party program through a COM connection. I was tasked to strengthen the resilency of our application, in order to do that I wait until the third-party application is ready. I do this by waiting until the return value on a method that returns true only when the third-party application has been fully loaded.
In an effort to avoid the condition where the application crashes during this procedure, and my application just sits there waiting throwing COM errors( caught of course ) I was wondering if the Exited event on the Process itself, is guaranteed to always happen?
I am more then willing to provide additional details when its possible. I am also for the time being limited to .NET Framework 2.0 with this current build.
It depends on the sort of crash - some crashes leave the "process" in memory (for example just stuck in some never-ending loop OR that COM object opened some modal error dialog and waits for user)... these cases are not covered by any method mentioned in your description...
In my experience to be really resilient you need a combination:
hook the Exited event (if you started the application via Process) OR find the process ID and monitor that
catch any exceptions from that COM object
implement a timeout + abort logic for calls to that COM object/application
"monitor" the COM object/app
I usually start a separate thread before calling such a COM object... that thread monitors the COM object/application for example if it open any window it is not supposed or memory consumption goes through the roof when it is not supposed to etc. - the things monitored and the reaction to each of them is rather specific to that COM object/application...
There are already some pretty good threads on this topic on Stack Overflow, but there doesn't really seem to be a concise answer on any of them. My C# console application (running as a Windows service) launches a Java process and manages it (starts/stops/restarts it), but my issue is that I will remote into machines, and see it has started about 20 Java processes sometimes.
This is obviously an issue with my application crashing at some point, and not shutting down the Java process it started. I have hooked "UnhandledExceptionEventHandler" in the AppDomain.CurrentDomain, and I call TerminateProcess() from it (shuts down the active Java process) but this issue is still occuring on occassion.
My application has the Main thread, a TCP Server Thread (which accepts async connections), and a UDP Server Thread. Is there anything else I should be hooking into on top of UnhandledException?
EDIT
It also just occured to me that I have a few Try/Catch blocks in my code that simply write to console, which I never see. Should I just remove these so these are caught by the UnhandledException or add a logger there instead?
First of all you have to change the Console.WriteLine.. lines in you code to Debug.WriteLine.. if you don't want to log, so the output of it will only be on debug.
Second when any exception occurs if you don't know how to handle it or fix it then rethrow it catch { throw; } after logging. I personally do
try
{
...
}
catch (Exception exception)
{
Log(exceptiosn);//log it first or Debug.WriteLine...
#if DEBUG
System.Diagnostics.Debugger.Break();//break at the debugger here.
#endif//DEBUG
throw;
}
After you cleaning up you code, now you can whenever DomainUnhandledException thrown, you can restart your application. an example will be here, The idea is you start a new instance from your application and then terminate the first one. you also define a mutex so only one instance at time will be alive.
Something to consider is whether you want the .NET application to be responsible for the spawned processes. If possible, they might be made responsible for shutting down when no longer receiving input. If the spawned processes are running on other machines I would try to do that anyway because network problems might interfere with sending a shutdown message from the .NET application to the Java processes. Each its own responsibilities.
That said, getting exception handling in the .NET application fixed (especially when you are missing some exceptions) is also important. Make each thread responsible for its exceptions and make sure you log them for easy debugging.