diff --git a/src/LiquidCode.Tester.Gateway/Services/WorkerClientService.cs b/src/LiquidCode.Tester.Gateway/Services/WorkerClientService.cs index b37b2fe..18ee4a6 100644 --- a/src/LiquidCode.Tester.Gateway/Services/WorkerClientService.cs +++ b/src/LiquidCode.Tester.Gateway/Services/WorkerClientService.cs @@ -35,7 +35,7 @@ public class WorkerClientService : IWorkerClientService form.Add(new StringContent(submit.MissionId.ToString()), "MissionId"); form.Add(new StringContent(submit.Language), "Language"); form.Add(new StringContent(submit.LanguageVersion), "LanguageVersion"); - form.Add(new StringContent(submit.SourceCode), "SourceCode"); + form.Add(new StringContent(submit.SourceCode, System.Text.Encoding.UTF8, "text/plain"), "SourceCode"); form.Add(new StringContent(submit.CallbackUrl), "CallbackUrl"); // Add package file diff --git a/src/LiquidCode.Tester.Worker/Services/CSharpCompilationServiceIsolate.cs b/src/LiquidCode.Tester.Worker/Services/CSharpCompilationServiceIsolate.cs index 8f82480..e1343c3 100644 --- a/src/LiquidCode.Tester.Worker/Services/CSharpCompilationServiceIsolate.cs +++ b/src/LiquidCode.Tester.Worker/Services/CSharpCompilationServiceIsolate.cs @@ -103,7 +103,10 @@ public class CSharpCompilationServiceIsolate : ICompilationService DirectoryBindings = new List { new DirectoryBinding { HostPath = "/usr/lib", SandboxPath = "/usr/lib", ReadOnly = true }, - new DirectoryBinding { HostPath = "/lib", SandboxPath = "/lib", ReadOnly = true } + new DirectoryBinding { HostPath = "/lib", SandboxPath = "/lib", ReadOnly = true }, + new DirectoryBinding { HostPath = "/usr/bin", SandboxPath = "/usr/bin", ReadOnly = true }, + new DirectoryBinding { HostPath = "/usr/share", SandboxPath = "/usr/share", ReadOnly = true }, + new DirectoryBinding { HostPath = "/etc/mono", SandboxPath = "/etc/mono", ReadOnly = true } } }); diff --git a/src/LiquidCode.Tester.Worker/Services/CSharpExecutionServiceIsolate.cs b/src/LiquidCode.Tester.Worker/Services/CSharpExecutionServiceIsolate.cs index 3261ea9..47101ee 100644 --- a/src/LiquidCode.Tester.Worker/Services/CSharpExecutionServiceIsolate.cs +++ b/src/LiquidCode.Tester.Worker/Services/CSharpExecutionServiceIsolate.cs @@ -1,5 +1,6 @@ using System.Diagnostics; using LiquidCode.Tester.Worker.Services.Isolate; +using System.Collections.Generic; namespace LiquidCode.Tester.Worker.Services; @@ -63,6 +64,7 @@ public class CSharpExecutionServiceIsolate : IExecutionService // Prepare input/output files inside the sandbox var outputFilePath = Path.Combine(boxDir, "output.txt"); + var stderrFilePath = Path.Combine(boxDir, "stderr.txt"); string? sandboxInputPath = null; if (!string.IsNullOrEmpty(inputFilePath) && File.Exists(inputFilePath)) @@ -71,20 +73,30 @@ public class CSharpExecutionServiceIsolate : IExecutionService File.Copy(inputFilePath, sandboxInputPath, overwrite: true); } - // Run in Isolate + // Run in Isolate using mono runtime var isolateResult = await _isolateService.RunAsync(new IsolateRunOptions { BoxId = boxId, - Executable = $"/box/{executableName}", + Executable = "/usr/bin/mono", + Arguments = new[] { $"/box/{executableName}" }, TimeLimitSeconds = timeLimitMs / 1000.0, WallTimeLimitSeconds = (timeLimitMs / 1000.0) * 2, MemoryLimitKb = memoryLimitMb * 1024, StackLimitKb = 256 * 1024, - ProcessLimit = 1, // Single process for C# + ProcessLimit = 64, // Mono may create multiple threads/processes EnableNetwork = false, StdinFile = sandboxInputPath, StdoutFile = outputFilePath, - WorkingDirectory = "/box" + StderrFile = stderrFilePath, + WorkingDirectory = "/box", + DirectoryBindings = new List + { + new DirectoryBinding { HostPath = "/usr/lib", SandboxPath = "/usr/lib", ReadOnly = true }, + new DirectoryBinding { HostPath = "/lib", SandboxPath = "/lib", ReadOnly = true }, + new DirectoryBinding { HostPath = "/usr/share", SandboxPath = "/usr/share", ReadOnly = true }, + new DirectoryBinding { HostPath = "/etc/mono", SandboxPath = "/etc/mono", ReadOnly = true }, + new DirectoryBinding { HostPath = "/usr/bin", SandboxPath = "/usr/bin", ReadOnly = true } + } }); stopwatch.Stop(); @@ -95,10 +107,19 @@ public class CSharpExecutionServiceIsolate : IExecutionService result.Output = await File.ReadAllTextAsync(outputFilePath); } + // Read stderr + var stderrContent = string.Empty; + if (File.Exists(stderrFilePath)) + { + stderrContent = await File.ReadAllTextAsync(stderrFilePath); + } + // Map Isolate result to ExecutionResult result.ExecutionTimeMs = (long)(isolateResult.CpuTimeSeconds * 1000); result.MemoryUsedMb = isolateResult.MemoryUsedKb / 1024; - result.ErrorOutput = isolateResult.ErrorOutput; + result.ErrorOutput = string.IsNullOrEmpty(stderrContent) + ? isolateResult.ErrorOutput + : $"{stderrContent}\n{isolateResult.ErrorOutput}".Trim(); result.ExitCode = isolateResult.ExitCode; if (isolateResult.TimeLimitExceeded)