private static void RunNodeJs()
        {
            const string NodeJsExe              = @"C:\Program Files\nodejs\node.exe";
            const string JsFilePath             = @"C:\Temp\code.js";
            const string JsFileWorkingDirectory = @"C:\Temp";

            File.WriteAllText(JsFilePath, GlobalConstants.SampleJavaScriptCode);

            var process = new RestrictedProcess(NodeJsExe, JsFileWorkingDirectory, new List <string>()
            {
                JsFilePath
            });

            process.StandardInput.WriteLine("Vasko" + Environment.NewLine + "Niki2" + Environment.NewLine + "Niki3");
            process.Start(1000, 100 * 1024 * 1024);
            process.StandardInput.Close();
            var output = process.StandardOutput.ReadToEnd();
            var error  = process.StandardError.ReadToEnd();

            Console.WriteLine(output);
            Console.WriteLine(error);
            Console.WriteLine(process.ExitCode);
        }
Example #2
0
        // TODO: double check and maybe change order of parameters
        public ProcessExecutionResult Execute(string fileName, string inputData, int timeLimit, int memoryLimit, IEnumerable <string> executionArguments = null)
        {
            var result = new ProcessExecutionResult {
                Type = ProcessExecutionResultType.Success
            };
            var workingDirectory = new FileInfo(fileName).DirectoryName;

            using (var restrictedProcess = new RestrictedProcess(fileName, workingDirectory, executionArguments, Math.Max(4096, (inputData.Length * 2) + 4)))
            {
                // Write to standard input using another thread
                restrictedProcess.StandardInput.WriteLineAsync(inputData).ContinueWith(
                    delegate
                {
                    // ReSharper disable once AccessToDisposedClosure
                    if (!restrictedProcess.IsDisposed)
                    {
                        // ReSharper disable once AccessToDisposedClosure
                        restrictedProcess.StandardInput.FlushAsync().ContinueWith(
                            delegate
                        {
                            restrictedProcess.StandardInput.Close();
                        });
                    }
                });

                // Read standard output using another thread to prevent process locking (waiting us to empty the output buffer)
                var processOutputTask = restrictedProcess.StandardOutput.ReadToEndAsync().ContinueWith(
                    x =>
                {
                    result.ReceivedOutput = x.Result;
                });

                // Read standard error using another thread
                var errorOutputTask = restrictedProcess.StandardError.ReadToEndAsync().ContinueWith(
                    x =>
                {
                    result.ErrorOutput = x.Result;
                });

                // Read memory consumption every few milliseconds to determine the peak memory usage of the process
                const int TimeIntervalBetweenTwoMemoryConsumptionRequests = 45;
                var       memoryTaskCancellationToken = new CancellationTokenSource();
                var       memoryTask = Task.Run(
                    () =>
                {
                    while (true)
                    {
                        // ReSharper disable once AccessToDisposedClosure
                        var peakWorkingSetSize = restrictedProcess.PeakWorkingSetSize;

                        result.MemoryUsed = Math.Max(result.MemoryUsed, peakWorkingSetSize);

                        if (memoryTaskCancellationToken.IsCancellationRequested)
                        {
                            return;
                        }

                        Thread.Sleep(TimeIntervalBetweenTwoMemoryConsumptionRequests);
                    }
                },
                    memoryTaskCancellationToken.Token);

                // Start the process
                restrictedProcess.Start(timeLimit, memoryLimit);

                // Wait the process to complete. Kill it after (timeLimit * 1.5) milliseconds if not completed.
                // We are waiting the process for more than defined time and after this we compare the process time with the real time limit.
                var exited = restrictedProcess.WaitForExit((int)(timeLimit * 1.5));
                if (!exited)
                {
                    restrictedProcess.Kill();
                    result.Type = ProcessExecutionResultType.TimeLimit;
                }

                // Close the memory consumption check thread
                memoryTaskCancellationToken.Cancel();
                try
                {
                    // To be sure that memory consumption will be evaluated correctly
                    memoryTask.Wait(TimeIntervalBetweenTwoMemoryConsumptionRequests);
                }
                catch (AggregateException ex)
                {
                    logger.Warn("AggregateException caught.", ex.InnerException);
                }

                // Close the task that gets the process error output
                try
                {
                    errorOutputTask.Wait(100);
                }
                catch (AggregateException ex)
                {
                    logger.Warn("AggregateException caught.", ex.InnerException);
                }

                // Close the task that gets the process output
                try
                {
                    processOutputTask.Wait(100);
                }
                catch (AggregateException ex)
                {
                    logger.Warn("AggregateException caught.", ex.InnerException);
                }

                Debug.Assert(restrictedProcess.HasExited, "Restricted process didn't exit!");

                // Report exit code and total process working time
                result.ExitCode   = restrictedProcess.ExitCode;
                result.TimeWorked = restrictedProcess.ExitTime - restrictedProcess.StartTime;
                result.PrivilegedProcessorTime = restrictedProcess.PrivilegedProcessorTime;
                result.UserProcessorTime       = restrictedProcess.UserProcessorTime;
            }

            if (result.TotalProcessorTime.TotalMilliseconds > timeLimit)
            {
                result.Type = ProcessExecutionResultType.TimeLimit;
            }

            if (!string.IsNullOrEmpty(result.ErrorOutput))
            {
                result.Type = ProcessExecutionResultType.RunTimeError;
            }

            if (result.MemoryUsed > memoryLimit)
            {
                result.Type = ProcessExecutionResultType.MemoryLimit;
            }

            return(result);
        }
        public override string Execute(string message)
        {
            var parts = message.Split(' ', 2);

            if (parts.Length != 2)
            {
                return("Usage: !calc [expression]");
            }

            try
            {
                var expression    = parts[1].TrimEnd();
                var code          = $@"using System;
using System.Linq;
using static System.Math;
namespace ExpressionEvaluation
{{
    public static class Program
    {{
        public static void Main()
        {{
            Console.WriteLine({expression});
        }}

        public static double Factorial(double n)
        {{
            double result = 1;
            for (int i = 2; i <= n; i++)
            {{
                result *= i;
            }}

            return result;
        }}
    }}
}}";
                var dotNetCoreDir = Path.GetDirectoryName(typeof(object).Assembly.Location);
                var compilation   = CSharpCompilation.Create("ExpressionEvaluation")
                                    .WithOptions(new CSharpCompilationOptions(OutputKind.ConsoleApplication))
                                    .AddReferences(
                    MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
                    MetadataReference.CreateFromFile(typeof(Console).Assembly.Location),
                    MetadataReference.CreateFromFile(typeof(Enumerable).Assembly.Location),
                    MetadataReference.CreateFromFile(Path.Combine(dotNetCoreDir, "System.Runtime.dll")))
                                    .AddSyntaxTrees(SyntaxFactory.ParseSyntaxTree(code));
                Directory.CreateDirectory(@"C:\Temp");
                File.WriteAllText(@"C:\Temp\ExpressionEvaluation.runtimeconfig.json", this.GenerateRuntimeConfig());
                var compilationResult = compilation.Emit(@"C:\Temp\ExpressionEvaluation.dll");
                if (!compilationResult.Success)
                {
                    return("Code error: " + string.Join(
                               "; ",
                               compilationResult.Diagnostics.Where(x => x.Severity == DiagnosticSeverity.Error)
                               .Select(x => x.GetMessage())));
                }

                var process = new RestrictedProcess("dotnet.exe", @"C:\Temp", new List <string> {
                    "ExpressionEvaluation.dll"
                });
                process.Start(1500, 8 * 1024 * 1024);
                var output = process.StandardOutput.ReadToEnd();
                var error  = process.StandardError.ReadToEnd();
                if (!string.IsNullOrWhiteSpace(error))
                {
                    return($"Execution error: {error}");
                }

                return($"Result: {output}");
            }
            catch (Exception e)
            {
                return($"Error: {e.Message}");
            }
        }
Example #4
0
        public static void Execute(string fileName, string inputData, int timeLimit, int memoryLimit, IEnumerable <string> executionArguments = null)
        {
            result = "ok";
            var workingDirectory = new FileInfo(fileName).DirectoryName;

            using (var restrictedProcess = new RestrictedProcess(fileName, workingDirectory, executionArguments, Math.Max(4096, (inputData.Length * 2) + 4)))
            {
                restrictedProcess.StandardInput.WriteLineAsync(inputData).ContinueWith(
                    delegate
                {
                    if (!restrictedProcess.IsDisposed)
                    {
                        restrictedProcess.StandardInput.FlushAsync().ContinueWith(
                            delegate
                        {
                            restrictedProcess.StandardInput.Close();
                        });
                    }
                });

                var processOutputTask = restrictedProcess.StandardOutput.ReadToEndAsync().ContinueWith(
                    x =>
                {
                    output = x.Result;
                });

                var errorOutputTask = restrictedProcess.StandardError.ReadToEndAsync().ContinueWith(
                    x =>
                {
                    erroroutput = x.Result;
                });

                const int TimeIntervalBetweenTwoMemoryConsumptionRequests = 45;
                var       memoryTaskCancellationToken = new CancellationTokenSource();
                var       memoryTask = Task.Run(
                    () =>
                {
                    while (true)
                    {
                        var peakWorkingSetSize = restrictedProcess.PeakWorkingSetSize;

                        memoryused = Math.Max(memoryused, peakWorkingSetSize);

                        if (memoryTaskCancellationToken.IsCancellationRequested)
                        {
                            return;
                        }

                        Thread.Sleep(TimeIntervalBetweenTwoMemoryConsumptionRequests);
                    }
                },
                    memoryTaskCancellationToken.Token);

                restrictedProcess.Start(timeLimit, memoryLimit);

                var exited = restrictedProcess.WaitForExit((int)(timeLimit * 1.5));
                if (!exited)
                {
                    restrictedProcess.Kill();
                    result = "tl";
                }

                memoryTaskCancellationToken.Cancel();
                try
                {
                    memoryTask.Wait(TimeIntervalBetweenTwoMemoryConsumptionRequests);
                }
                catch (AggregateException ex)
                {
                }

                try
                {
                    errorOutputTask.Wait(100);
                }
                catch (AggregateException ex)
                {
                }

                try
                {
                    processOutputTask.Wait(100);
                }
                catch (AggregateException ex)
                {
                }

                Debug.Assert(restrictedProcess.HasExited, "Restricted process didn't exit!");

                exitcode          = restrictedProcess.ExitCode;
                time              = restrictedProcess.ExitTime - restrictedProcess.StartTime;
                processortime     = restrictedProcess.PrivilegedProcessorTime;
                userprocessortime = restrictedProcess.UserProcessorTime;
            }

            if ((processortime + userprocessortime).TotalMilliseconds > timeLimit)
            {
                result = "tl";
            }

            if (!string.IsNullOrEmpty(erroroutput))
            {
                result = "re";
            }

            if (memoryused > memoryLimit)
            {
                result = "ml";
            }
        }