static RundotnetData RunDotNet(RundotnetData data)
{
int compilationTimeInMs;
CompilerParameters cp = new CompilerParameters();
cp.GenerateExecutable = false;
Random rg = Utils.Utils.GetTrulyRandom();
string folder = reExp.Utils.Utils.RootFolder + @"\executables\usercode\";
string assemblyName = "userAssembly_" + rg.Next(0, 10000000);
string path = folder + assemblyName + ".dll";
cp.OutputAssembly = path;
// Save the assembly as a physical file.
cp.GenerateInMemory = false;
// Set whether to treat all warnings as errors.
cp.TreatWarningsAsErrors = false;
cp.WarningLevel = 4;
cp.IncludeDebugInformation = false;
cp.ReferencedAssemblies.Add("System.dll");
cp.ReferencedAssemblies.Add("System.Core.dll");
cp.ReferencedAssemblies.Add("System.Numerics.dll");
cp.ReferencedAssemblies.Add("System.Data.dll");
cp.ReferencedAssemblies.Add("System.Data.DataSetExtensions.dll");
cp.ReferencedAssemblies.Add("System.Xml.dll");
cp.ReferencedAssemblies.Add("System.Xml.Linq.dll");
cp.ReferencedAssemblies.Add("System.Drawing.dll");
if (data.LanguageChoice == LanguagesEnum.CSharp)
cp.ReferencedAssemblies.Add("Microsoft.CSharp.dll");
else if (data.LanguageChoice == LanguagesEnum.VB)
cp.ReferencedAssemblies.Add("Microsoft.VisualBasic.dll");
cp.ReferencedAssemblies.Add(typeof(System.ComponentModel.DataAnnotations.DisplayAttribute).Assembly.Location);
cp.ReferencedAssemblies.Add(typeof(System.ComponentModel.Composition.ImportAttribute).Assembly.Location);
cp.ReferencedAssemblies.Add(typeof(System.Web.HttpRequest).Assembly.Location);
cp.ReferencedAssemblies.Add(typeof(System.Net.Http.HttpClient).Assembly.Location);
cp.ReferencedAssemblies.Add(typeof(Newtonsoft.Json.JsonSerializer).Assembly.Location);
//cp.ReferencedAssemblies.Add(typeof(System.Windows.Threading.DispatcherTimer).Assembly.Location);
CompilerResults cr = null;
using (var provider = GetProvider(data.LanguageChoice))
{
DateTime comp_start = DateTime.Now;
// Invoke compilation of the source file.
cr = provider.CompileAssemblyFromSource(cp, new string[] { data.Program });
compilationTimeInMs = (int)(DateTime.Now - comp_start).TotalMilliseconds;
}
var messages = cr.Errors.Cast<CompilerError>();
var warnings = messages.Where(f => f.IsWarning == true);
var errors = messages.Where(f => f.IsWarning == false);
if (warnings.Count() != 0)
{
foreach (var warn in warnings)
data.Warnings.Add(string.Format("({0}:{1}) {2}", warn.Line, warn.Column, warn.ErrorText));
}
if (errors.Count() != 0)
{
foreach (var ce in errors)
{
data.Errors.Add(string.Format("({0}:{1}) {2}", ce.Line, ce.Column, ce.ErrorText));
}
Utils.Log.LogCodeToDB(data.Program, data.Input, data.CompilerArgs, "Compilation errors", (int)data.LanguageChoice, data.IsApi, false);
data.RunStats = string.Format("Compilation time: {0} s", Math.Round((compilationTimeInMs / (double)1000), 2));
return data;
}
else
{
using (Process process = new Process())
{
try
{
double TotalMemoryInBytes = 0;
double TotalThreadCount = 0;
int samplesCount = 0;
process.StartInfo.FileName = reExp.Utils.Utils.RootFolder + "executables/SpawnedProcess.exe";
process.StartInfo.Arguments = folder.Replace(" ", "|_|") + " " + assemblyName + " Rextester|Program|Main";
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.RedirectStandardInput = true;
DateTime start = DateTime.Now;
process.Start();
//try
//{
// process.PriorityClass = ProcessPriorityClass.BelowNormal;
//}
//catch (Exception)
//{ }
if (!string.IsNullOrEmpty(data.Input))
{
InputWriter input = new InputWriter(process.StandardInput, data.Input);
Thread inputWriter = new Thread(new ThreadStart(input.Writeinput));
inputWriter.Start();
}
OutputReader output = new OutputReader(process.StandardOutput);
Thread outputReader = new Thread(new ThreadStart(output.ReadOutput));
outputReader.Start();
OutputReader error = new OutputReader(process.StandardError);
Thread errorReader = new Thread(new ThreadStart(error.ReadOutput));
errorReader.Start();
do
{
// Refresh the current process property values.
process.Refresh();
if (!process.HasExited)
{
try
{
var proc = process.TotalProcessorTime;
// Update the values for the overall peak memory statistics.
var mem1 = process.PagedMemorySize64;
var mem2 = process.PrivateMemorySize64;
//update stats
TotalMemoryInBytes += (mem1 + mem2);
TotalThreadCount += (process.Threads.Count);
samplesCount++;
if (proc.TotalSeconds > 5 || mem1 + mem2 > 100000000 || process.Threads.Count > 100 || start + TimeSpan.FromSeconds(10) < DateTime.Now)
{
var time = proc.TotalSeconds;
var mem = mem1 + mem2;
process.Kill();
var res = string.Format("Process killed because it exceeded given resources.\nCpu time used {0} sec, absolute running time {1} sec, memory used {2} Mb, nr of threads {3}", time, (int)(DateTime.Now - start).TotalSeconds, (int)(mem / 1048576), process.Threads.Count);
data.Errors.Add(res);
string partialResult = output.Builder.ToString();
data.Output = partialResult;
Utils.Log.LogCodeToDB(data.Program, data.Input, data.CompilerArgs, res, (int)data.LanguageChoice, data.IsApi, false);
data.RunStats = string.Format("Compilation time: {0} sec, absolute running time: {1} sec, cpu time: {2} sec, average memory usage: {3} Mb, average nr of threads: {4}",
Math.Round((compilationTimeInMs / (double)1000), 2),
Math.Round((DateTime.Now - start).TotalSeconds, 2),
Math.Round(proc.TotalSeconds, 2),
samplesCount != 0 ? (int?)((TotalMemoryInBytes / samplesCount) / 1048576) : null,
samplesCount != 0 ? (int?)(TotalThreadCount / samplesCount) : null);
return data;
}
}
catch (InvalidOperationException)
{
break;
}
}
}
while (!process.WaitForExit(10));
process.WaitForExit();
data.RunStats = string.Format("Compilation time: {0} sec, absolute running time: {1} sec, cpu time: {2} sec, average memory usage: {3} Mb, average nr of threads: {4}",
Math.Round((compilationTimeInMs / (double)1000), 2),
Math.Round((process.ExitTime - process.StartTime).TotalSeconds, 2),
Math.Round(process.TotalProcessorTime.TotalSeconds, 2),
samplesCount != 0 ? (int?)((TotalMemoryInBytes / samplesCount) / 1048576) : null,
samplesCount != 0 ? (int?)(TotalThreadCount / samplesCount) : null);
errorReader.Join(5000);
outputReader.Join(5000);
if (!string.IsNullOrEmpty(error.Output))
{
data.Output = output.Builder.ToString();
data.Errors.Add(error.Output);
Utils.Log.LogCodeToDB(data.Program, data.Input, data.CompilerArgs, error.Output, (int)data.LanguageChoice, data.IsApi, false);
return data;
}
data.Output = output.Output;
Utils.Log.LogCodeToDB(data.Program, data.Input, data.CompilerArgs, "OK", (int)data.LanguageChoice, data.IsApi, true);
return data;
}
catch (Exception e)
{
if (!process.HasExited)
{
reExp.Utils.Log.LogInfo("Process left running " + e.Message, e, "RunDotNet");
}
throw;
}
finally
{
reExp.Utils.CleanUp.DeleteFile(path);
}
}
}
}