[High] Code execution TimeoutSeconds not enforced on worker #59

Closed
opened 2026-05-05 04:15:23 +00:00 by spikerj · 1 comment
Owner

Severity: High (resource safety)

File: SpikerSoft.EventHandlers.CodeExecution/Services/CodeExecutionWorkerHostedService.cs (~298)

Problem: worker.ExecuteCodeAsync(request) is called without any CancellationToken linked to request.TimeoutSeconds. Roslyn's ExecuteFreePlayAsync only checks cancellation at the start, not around emit/invoke. If student code hangs (infinite loop, blocking I/O), nothing kills it.

Fix:

using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(request.TimeoutSeconds));
using var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(cts.Token, stoppingToken);
var response = await worker.ExecuteCodeAsync(request, linkedCts.Token);

Also ensure RoslynCodeExecutor checks the token periodically inside execution.

Acceptance criteria:

  • Infinite-loop student code is killed within TimeoutSeconds + small buffer
  • Test with while(true){} confirms cancellation
  • No regression for legitimate quick executions
**Severity:** High (resource safety) **File:** `SpikerSoft.EventHandlers.CodeExecution/Services/CodeExecutionWorkerHostedService.cs` (~298) **Problem:** `worker.ExecuteCodeAsync(request)` is called without any `CancellationToken` linked to `request.TimeoutSeconds`. Roslyn's `ExecuteFreePlayAsync` only checks cancellation at the start, not around emit/invoke. If student code hangs (infinite loop, blocking I/O), nothing kills it. **Fix:** ```csharp using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(request.TimeoutSeconds)); using var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(cts.Token, stoppingToken); var response = await worker.ExecuteCodeAsync(request, linkedCts.Token); ``` Also ensure `RoslynCodeExecutor` checks the token periodically inside execution. **Acceptance criteria:** - [ ] Infinite-loop student code is killed within `TimeoutSeconds + small buffer` - [ ] Test with `while(true){}` confirms cancellation - [ ] No regression for legitimate quick executions
Author
Owner

Resolved.

CodeExecutionWorkerHostedService now enforces request.TimeoutSeconds per message:

  • Captured stoppingToken into _shutdownToken field at ExecuteAsync start
  • In OnCodeExecutionRequestReceived, builds a CancellationTokenSource(timeout) linked with _shutdownToken
  • request.TimeoutSeconds is clamped to [1, 300] via MaxExecutionTimeout = 5 minutes to bound worst-case worker load even if a misconfigured client claims an enormous timeout
  • worker.ExecuteCodeAsync(request, linkedCts.Token) now receives the linked token
  • OperationCanceledException from a tripped timeout is caught and turned into a CodeExecutionResponse with Success = false and a clear error message

File: SpikerSoft.EventHandlers.CodeExecution/Services/CodeExecutionWorkerHostedService.cs.

**Resolved.** `CodeExecutionWorkerHostedService` now enforces `request.TimeoutSeconds` per message: - Captured `stoppingToken` into `_shutdownToken` field at `ExecuteAsync` start - In `OnCodeExecutionRequestReceived`, builds a `CancellationTokenSource(timeout)` linked with `_shutdownToken` - `request.TimeoutSeconds` is clamped to `[1, 300]` via `MaxExecutionTimeout = 5 minutes` to bound worst-case worker load even if a misconfigured client claims an enormous timeout - `worker.ExecuteCodeAsync(request, linkedCts.Token)` now receives the linked token - `OperationCanceledException` from a tripped timeout is caught and turned into a `CodeExecutionResponse` with `Success = false` and a clear error message File: `SpikerSoft.EventHandlers.CodeExecution/Services/CodeExecutionWorkerHostedService.cs`.
Sign in to join this conversation.