Out of memory when starting process from c# and mono - c#

I am working with an embedded linux board (Atmel AT91SAM) with Debian installed. There is a mono application running and its switching an output from GPIO on/off periodicly (like every 500ms) by calling cat by starting a new System Process with bash. After some time I get an "Out of memory" exception and output is not set for a time, after it "recovers itself" after some seconds.
Is this a bad idea to set the pioC10 this way? If so, how else should
I set the value file?
Could this memory exception occur, because of
not being able to access the GPIO at the moment?
Is there a clean way to dispose the process, or is it done when method is closed automatically?
private void OnTimer1Event(object source, ElapsedEventArgs e)
{
alternateBlinkTimer1.Stop();
alternateBlinkTimer2.Start();
try
{
var processStartInfo = new ProcessStartInfo { FileName = "/bin/bash", Arguments = "-c \"echo 1 > /sys/class/gpio/pioC10/value\"" };
System.Diagnostics.Process process = new Process();
process.StartInfo = processStartInfo;
process.Start();
}
catch (Exception err)
{
log.Error(err.Message);
}
}

You can try skipping the Process Class and any memory management/garbage collection associated to it by directly use libc's system.
In your Class that you are defining the OnTimer1Event method, add a definition to system:
[DllImport ("libc")]
private static extern int system (string exec);
Then you can:
private void OnTimer1Event(object source, ElapsedEventArgs e)
{
alternateBlinkTimer1.Stop();
alternateBlinkTimer2.Start();
system("echo 1 > /sys/class/gpio/pioC10/value\");
}

Related

How to make a process crash if it doesn't log anything for 5 minutes

I work at Ubisoft and we use a very old program to manipulate some files. Since it's legacy software, it's really bad and it may happen that the software has crashed and keeps on running. We sadly don't have access to the code, so we're unable to fix that. I was wondering, is it possible to use System.Diagnostics.Process with a "no log timeout"? Here's what I'm trying to achieve
var legacySoftwareProcess = new Process
{
StartInfo =
{
UseShellExecute = false,
RedirectStandardOutput = true,
WorkingDirectory = localPackageFolder,
FileName = CiConfig.DataGeneration.RebuildUnstrippedBatName
}
};
legacySoftwareProcess.IdleLogTimeout = 5 * 60; // 5 minutes
legacySoftwareProcess.Start();
var output = proc.StandardOutput.ReadToEnd();
legacySoftwareProcess.WaitForExit();
if (legacySoftwareProcess.ExitCode != 0)
{
Context.LogMessage(output);
Context.LogError("The process exited with non 0 code");
}
Rather than using:
var output = proc.StandardOutput.ReadToEnd();
You can listen for the event when output data is received from the process:
proc.OutputDataReceived += ResetTimer;
proc.Start();
proc.BeginOutputReadLine(); // not sure that you should use that as it may read output synchronously (I will check that soon)
And in the handler method ResetTimer, as the method name implies, reset a 5-minute timer:
static void ResetTimer(object sender, DataReceivedEventArgs e)
{
if (e.Data != null)
{
// reset the timer
}
}
If timer has elapsed, it means nothing has been outputed for 5 minutes, and you can take action accordingly, ie kill the process.

WPF programme not running correctly when run silently

I have written a small programme to perform a quick configuration on a client machine and it needs to be able to run with a GUI and silently from the command line. If I run it with the GUI then it works perfectly, if however I try to run it without then it just hangs.
I have traced the problem to this section of code:
string arg = "/C:\"setup.exe /qn ADD_OPINSIGHTS_WORKSPACE=1 OPINSIGHTS_WORKSPACE_ID=" + workSpaceID + " OPINSIGHTS_WORKSPACE_KEY=" + workSpaceKey + " AcceptEndUserLicenseAgreement=1\"";
log.Info(arg);
// Use ProcessStartInfo class
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.CreateNoWindow = false;
startInfo.UseShellExecute = false;
startInfo.FileName = "MMASetup-AMD64.exe";
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.Arguments = arg;
try
{
log.Info("try entered");
// Start the process with the info we specified.
// Call WaitForExit and then the using statement will close.
using (Process exeProcess = Process.Start(startInfo))
{
log.Info("Install started");
exeProcess.WaitForExit(30000);
log.Info("Install exit code: " + (exeProcess.ExitCode).ToString());
return (exeProcess.ExitCode).ToString();
}
}
catch (Exception e)
{
log.Error("MMA install threw an error: ", e);
return e.Message;
}
This method is in a seperate class to the GUI and silent code and is run in exactly the same way yet only reaches "Install started" when run silently. I know that the exe does finish so I have tried using the code in this solution but had the same problem:
ProcessStartInfo hanging on "WaitForExit"? Why?
I had the same Problem.
I made a startup class:
public partial class Startup {
// WPF App
private App _app;
[STAThread]
public static void Main(string[] args) {
try {
//Do what you need
//Check the args
//Start your setup silent
//start the WPF App if need it
this._app = new App();
this._app.InitializeComponent();
this._app.Run();
} catch (Exception ex) {
//Logging ex
}
}
After that you must change your Application Startup Object to the Startup Class.
I was running all of my work asynchronously and because I was not loading the GUI thread Windows was treating the application like a console app. Whereas a GUI thread would call other asynchronous methods and wait for them to finish a console application calls the methods and then closes because it has nothing left to do. The solution was to explicitly make the main thread wait like this:
public static void Main(string[] args)
{
try
{
Install().Wait();
}
catch (Exception ex)
{
}
}
private static async Task Install()
{}

C# Process StandardOutput. How to send Output from the ran EXE?

I have two programs, one is a game and one is a launcher for the game. I created the launcher, in the first place, to receive basic information from the game and detect any kind of exit (crashes, Task Manager process stop, etc)
I will attach my current code for the process runner, it seems like all solutions on the internet, but what I can't figure out is how to make the game send information to the launcher. I tried Console.WriteLine("login=..."); but it doesn't seem to send anything.
private void button1_Click(object sender, EventArgs e)
{
using (Process exeProcess = Process.Start(new ProcessStartInfo() { UseShellExecute = false,
FileName = "Game.exe",
WorkingDirectory = Environment.CurrentDirectory,
RedirectStandardOutput = true}))
{
string output = "";
while (!exeProcess.HasExited)
{
try
{
output += exeProcess.StandardOutput.ReadToEnd() + "\r\n";
}
catch (Exception exc)
{
output += exc.Message + "::" + exc.InnerException + "\r\n";
}
}
MessageBox.Show(output);
}
}
With respect to your code, by adding the following line you can obtain error messages that were thrown by the game.
RedirectStandardError = true,
If you are developing your game in .NET you can return appropriate error codes as follows. Based on the error code you can then display appropriate messages in you launcher
enum GameExitCodes
{
Normal=0,
UnknownError=-1,
OutOfMemory=-2
}
//Game Application
static void Main(string[] args)
{
try
{
// Start game
Environment.ExitCode = (int)GameExitCodes.Normal;
}
catch (OutOfMemoryException)
{
Environment.ExitCode = (int)GameExitCodes.OutOfMemory;
}
catch (Exception)
{
Environment.ExitCode = (int)GameExitCodes.UnknownError;
}
}
NOTE: You can take a look at this open source game launcher developed in C# as a reference or modify it as per your needs.
EDIT: Added info as per comment
There are multiple ways to enable communication between between 2 .NET processes. They are
Anonymous Pipes
Named Pipes
Using Win32 WM_COPYDATA
MSMQ

Restart an application by itself

I want to build my application with the function to restart itself. I found on codeproject
ProcessStartInfo Info=new ProcessStartInfo();
Info.Arguments="/C choice /C Y /N /D Y /T 3 & Del "+
Application.ExecutablePath;
Info.WindowStyle=ProcessWindowStyle.Hidden;
Info.CreateNoWindow=true;
Info.FileName="cmd.exe";
Process.Start(Info);
Application.Exit();
This does not work at all...
And the other problem is, how to start it again like this?
Maybe there are also arguments to start applications.
Edit:
http://www.codeproject.com/script/Articles/ArticleVersion.aspx?aid=31454&av=58703
I use similar code to the code you tried when restarting apps. I send a timed cmd command to restart the app for me like this:
ProcessStartInfo Info = new ProcessStartInfo();
Info.Arguments = "/C ping 127.0.0.1 -n 2 && \"" + Application.ExecutablePath + "\"";
Info.WindowStyle = ProcessWindowStyle.Hidden;
Info.CreateNoWindow = true;
Info.FileName = "cmd.exe";
Process.Start(Info);
Application.Exit();
The command is sent to the OS, the ping pauses the script for 2-3 seconds, by which time the application has exited from Application.Exit(), then the next command after the ping starts it again.
Note: The \" puts quotes around the path, incase it has spaces, which cmd can't process without quotes.
Hope this helps!
Why not use
Application.Restart();
??
More on Restart
Why not just the following?
Process.Start(Application.ExecutablePath);
Application.Exit();
If you want to be sure the app does not run twice either use Environment.Exit(-1) which kills the process instantaneously (not really the nice way) or something like starting a second app, which checks for the process of the main app and starts it again as soon as the process is gone.
You have the initial application A, you want to restart.
So, When you want to kill A, a little application B is started, B kill A, then B start A, and kill B.
To start a process:
Process.Start("A.exe");
To kill a process, is something like this
Process[] procs = Process.GetProcessesByName("B");
foreach (Process proc in procs)
proc.Kill();
A lot of people are suggesting to use Application.Restart. In reality, this function rarely performs as expected. I have never had it shut down the application I am calling it from. I have always had to close the application through other methods such as closing the main form.
You have two ways of handling this. You either have an external program that closes the calling process and starts a new one,
or,
you have the start of your new software kill other instances of same application if an argument is passed as restart.
private void Application_Startup(object sender, StartupEventArgs e)
{
try
{
if (e.Args.Length > 0)
{
foreach (string arg in e.Args)
{
if (arg == "-restart")
{
// WaitForConnection.exe
foreach (Process p in Process.GetProcesses())
{
// In case we get Access Denied
try
{
if (p.MainModule.FileName.ToLower().EndsWith("yourapp.exe"))
{
p.Kill();
p.WaitForExit();
break;
}
}
catch
{ }
}
}
}
}
}
catch
{
}
}
Winforms has the Application.Restart() method, which does just that. If you're using WPF, you can simply add a reference to System.Windows.Forms and call it.
Another way of doing this which feels a little cleaner than these solutions is to run a batch file which includes a specific delay to wait for the current application to terminate. This has the added benefit of preventing the two application instances from being open at the same time.
Example windows batch file ("restart.bat"):
sleep 5
start "" "C:\Dev\MyApplication.exe"
In the application, add this code:
// Launch the restart batch file
Process.Start(#"C:\Dev\restart.bat");
// Close the current application (for WPF case)
Application.Current.MainWindow.Close();
// Close the current application (for WinForms case)
Application.Exit();
My solution:
private static bool _exiting;
private static readonly object SynchObj = new object();
public static void ApplicationRestart(params string[] commandLine)
{
lock (SynchObj)
{
if (Assembly.GetEntryAssembly() == null)
{
throw new NotSupportedException("RestartNotSupported");
}
if (_exiting)
{
return;
}
_exiting = true;
if (Environment.OSVersion.Version.Major < 6)
{
return;
}
bool cancelExit = true;
try
{
List<Form> openForms = Application.OpenForms.OfType<Form>().ToList();
for (int i = openForms.Count - 1; i >= 0; i--)
{
Form f = openForms[i];
if (f.InvokeRequired)
{
f.Invoke(new MethodInvoker(() =>
{
f.FormClosing += (sender, args) => cancelExit = args.Cancel;
f.Close();
}));
}
else
{
f.FormClosing += (sender, args) => cancelExit = args.Cancel;
f.Close();
}
if (cancelExit) break;
}
if (cancelExit) return;
Process.Start(new ProcessStartInfo
{
UseShellExecute = true,
WorkingDirectory = Environment.CurrentDirectory,
FileName = Application.ExecutablePath,
Arguments = commandLine.Length > 0 ? string.Join(" ", commandLine) : string.Empty
});
Application.Exit();
}
finally
{
_exiting = false;
}
}
}
This worked for me:
Process.Start(Process.GetCurrentProcess().MainModule.FileName);
Application.Current.Shutdown();
Some of the other answers have neat things like waiting for a ping to give the initial application time to wind down, but if you just need something simple, this is nice.
For .Net application solution looks like this:
System.Web.HttpRuntime.UnloadAppDomain()
I used this to restart my web application after changing AppSettings in myconfig file.
System.Configuration.Configuration configuration = WebConfigurationManager.OpenWebConfiguration("~");
configuration.AppSettings.Settings["SiteMode"].Value = model.SiteMode.ToString();
configuration.Save();

Killing Java Process from C# Console App

I posted about this a little while ago, but I resolved the other issue and ran into one more. I am about to deploy this program to 28 hosting machines so I want to make sure this is working before I do so.
I wrote a little c# NET application that is basically a wrapper for a Java application, when my app starts, the Java app starts, when my app closes, it closes, and so on.
Everything works properly except that when I close my application, the Java application continues to run. When I create the process, I store the Process var in a variable outside of the methods, and then use that when my application goes to shutdown. For whatever reason though it is not terminating the Java application.
class Program
{
private static Process minecraftProcess;
public static void LaunchMinecraft(String file, String memoryValue)
{
String memParams = "-Xmx" + memoryValue + "M" + " -Xms" + memoryValue + "M ";
String args = memParams + "-jar " + file + " nogui";
ProcessStartInfo processInfo = new ProcessStartInfo("java.exe", args);
processInfo.CreateNoWindow = true;
processInfo.UseShellExecute = false;
try
{
//using (Process minecraftProcess = Process.Start(processInfo))
using (minecraftProcess = Process.Start(processInfo))
{
minecraftProcess.WaitForExit();
}
}
catch
{
// Log Error
}
}
static void Main(string[] args)
{
Arguments CommandLine = new Arguments(args);
// Hook ProcessExit Event
AppDomain.CurrentDomain.ProcessExit += new EventHandler(Current_ProcessExit);
if (CommandLine["file"] != null && CommandLine["memory"] != null)
{
// Launch the Application (Command Line Parameters)
LaunchMinecraft(CommandLine["file"], CommandLine["memory"]);
}
else
{
// Launch the Application (Default Parameters)
LaunchMinecraft("minecraft_server.jar", "1024");
}
}
static void Current_ProcessExit(object sender, EventArgs e)
{
System.Threading.Thread.Sleep(10000);
// If we have an active Minecraft Service, Shut it down
if (minecraftProcess != null)
{
minecraftProcess.Kill();
}
}
}
You can't Sleep in a ProcessExit handler.
The documentation states:
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 two seconds.
An unmanaged host can change this
execution time by calling the
ICLRPolicyManager::SetTimeout method
with the OPR_ProcessExit enumeration
value.
Nevermind, I just realized the minecraftProcess variable is static.
Don't know if you did not solve this issue by yourself but:
You should be aware that there are Start methods for instances (returning bool) and static (returning a object).
You should not use using with something other than using-local variables!
Just this should work fine:
minecraftProcess = Process.Start(processInfo)
minecraftProcess.WaitForExit();

Categories