Exemple #1
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);
        }
Exemple #2
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";
            }
        }