There is no useC/useCpp (or general "use the language-aware free-play factory whenever metadata says so") branch. So a free-play submission through POST /api/CCodeRunner/run or POST /api/CppCodeRunner/run (which correctly stamp metadata.language = "c" / "cpp") falls through to ExecuteGeneralCodeAsync, which always compiles the submission as C# via Roslyn. It never reaches the registered CFreePlayCodeExecutor / CppFreePlayCodeExecutor (both exist and are wired up in SpikerSoft.EventHandlers.CodeExecution/Program.cs - they're just dead code for this path).
Practical effect: any real C/C++ free-play submission fails immediately with a C# compile error (e.g. #include isn't valid C#), regardless of whether the code is actually correct C/C++.
Lesson submissions are unaffected - ExecuteLessonCodeAsync dispatches via _gradingExecutorFactory.For(gradingRuntime), keyed off the lesson strategy's GradingRuntime (ClangC/ClangCpp), which correctly resolves ClangLessonGradingExecutor. Only the free-play/"run" endpoints are affected.
Suggested fix
Generalize the free-play dispatch condition to also cover C/C++ (e.g. check CodeExecutionMetadataHelper.IsCLanguage/IsCppLanguage alongside Python/JS, or better: always prefer _freePlayExecutorFactory when a non-C# language is present in metadata, falling back to ExecuteGeneralCodeAsync only for the C#/unset default).
Why not fixed alongside Phase 5 integration tests
Out of scope for a test-writing pass, and the in-process test fixture never registers the Clang executors anyway (needs wasi-sdk + wasmtime baked into the worker's Docker image), so this bug isn't observable from that fixture regardless - it was found by reading the dispatch code while designing the C/C++ coverage, not from a failing test.
## What's wrong
Discovered while writing Phase 5 of the Lessons integration test suite (spikersoft-backend#177 / spikersoft-issues#452).
`CodeExecutionWorkerService.ExecuteCodeAsync` in `SpikerSoft.EventHandlers.CodeExecution` decides how to run a **free-play** (no `LessonId`) submission with:
```csharp
var usePython = gradingRuntime == LessonGradingRuntime.CPython
|| (!request.LessonId.HasValue && CodeExecutionMetadataHelper.IsPythonLanguage(request.Metadata));
var useJavaScript = gradingRuntime == LessonGradingRuntime.NodeJavaScript
|| (!request.LessonId.HasValue && CodeExecutionMetadataHelper.IsJavaScriptLanguage(request.Metadata));
...
if (request.LessonId.HasValue) { response = await ExecuteLessonCodeAsync(request, cancellationToken); }
else if (usePython || useJavaScript) { response = await ExecuteNonCsharpFreePlayAsync(request, cancellationToken); }
else { response = await ExecuteGeneralCodeAsync(request); } // <- Roslyn C#
```
There is no `useC`/`useCpp` (or general "use the language-aware free-play factory whenever metadata says so") branch. So a free-play submission through `POST /api/CCodeRunner/run` or `POST /api/CppCodeRunner/run` (which correctly stamp `metadata.language = "c"` / `"cpp"`) falls through to `ExecuteGeneralCodeAsync`, which **always compiles the submission as C# via Roslyn**. It never reaches the registered `CFreePlayCodeExecutor` / `CppFreePlayCodeExecutor` (both exist and are wired up in `SpikerSoft.EventHandlers.CodeExecution/Program.cs` - they're just dead code for this path).
Practical effect: any real C/C++ free-play submission fails immediately with a C# compile error (e.g. `#include` isn't valid C#), regardless of whether the code is actually correct C/C++.
**Lesson submissions are unaffected** - `ExecuteLessonCodeAsync` dispatches via `_gradingExecutorFactory.For(gradingRuntime)`, keyed off the lesson strategy's `GradingRuntime` (`ClangC`/`ClangCpp`), which correctly resolves `ClangLessonGradingExecutor`. Only the free-play/`"run"` endpoints are affected.
## Suggested fix
Generalize the free-play dispatch condition to also cover C/C++ (e.g. check `CodeExecutionMetadataHelper.IsCLanguage`/`IsCppLanguage` alongside Python/JS, or better: always prefer `_freePlayExecutorFactory` when a non-C# `language` is present in metadata, falling back to `ExecuteGeneralCodeAsync` only for the C#/unset default).
## Why not fixed alongside Phase 5 integration tests
Out of scope for a test-writing pass, and the in-process test fixture never registers the Clang executors anyway (needs wasi-sdk + wasmtime baked into the worker's Docker image), so this bug isn't observable from that fixture regardless - it was found by reading the dispatch code while designing the C/C++ coverage, not from a failing test.
Resolved in spikersoft-backend PR #178 (merged to master). Added a useClang arm (keyed off CodeExecutionMetadataHelper.IsClangLanguage, free-play only) to the free-play dispatch in CodeExecutionWorkerService.ExecuteCodeAsync, so C/C++ submissions now reach the language-aware free-play factory (CFreePlayCodeExecutor/CppFreePlayCodeExecutor) instead of falling through to Roslyn C#. ExecuteNonCsharpFreePlayAsync already resolved the executor via _freePlayExecutorFactory.For(metadata), so no deeper change was needed. Keyed off metadata.language rather than a grading-runtime member since LessonGradingRuntime has no ClangC/ClangCpp. New CodeExecutionWorkerServiceTests theory (c, cpp) pins the routing; dotnet test SpikerSoft.Tests.Unit green. Closing.
Resolved in spikersoft-backend PR #178 (merged to `master`). Added a `useClang` arm (keyed off `CodeExecutionMetadataHelper.IsClangLanguage`, free-play only) to the free-play dispatch in `CodeExecutionWorkerService.ExecuteCodeAsync`, so C/C++ submissions now reach the language-aware free-play factory (`CFreePlayCodeExecutor`/`CppFreePlayCodeExecutor`) instead of falling through to Roslyn C#. `ExecuteNonCsharpFreePlayAsync` already resolved the executor via `_freePlayExecutorFactory.For(metadata)`, so no deeper change was needed. Keyed off `metadata.language` rather than a grading-runtime member since `LessonGradingRuntime` has no `ClangC`/`ClangCpp`. New `CodeExecutionWorkerServiceTests` theory (`c`, `cpp`) pins the routing; `dotnet test SpikerSoft.Tests.Unit` green. Closing.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
What's wrong
Discovered while writing Phase 5 of the Lessons integration test suite (spikersoft-backend#177 / spikersoft-issues#452).
CodeExecutionWorkerService.ExecuteCodeAsyncinSpikerSoft.EventHandlers.CodeExecutiondecides how to run a free-play (noLessonId) submission with:There is no
useC/useCpp(or general "use the language-aware free-play factory whenever metadata says so") branch. So a free-play submission throughPOST /api/CCodeRunner/runorPOST /api/CppCodeRunner/run(which correctly stampmetadata.language = "c"/"cpp") falls through toExecuteGeneralCodeAsync, which always compiles the submission as C# via Roslyn. It never reaches the registeredCFreePlayCodeExecutor/CppFreePlayCodeExecutor(both exist and are wired up inSpikerSoft.EventHandlers.CodeExecution/Program.cs- they're just dead code for this path).Practical effect: any real C/C++ free-play submission fails immediately with a C# compile error (e.g.
#includeisn't valid C#), regardless of whether the code is actually correct C/C++.Lesson submissions are unaffected -
ExecuteLessonCodeAsyncdispatches via_gradingExecutorFactory.For(gradingRuntime), keyed off the lesson strategy'sGradingRuntime(ClangC/ClangCpp), which correctly resolvesClangLessonGradingExecutor. Only the free-play/"run"endpoints are affected.Suggested fix
Generalize the free-play dispatch condition to also cover C/C++ (e.g. check
CodeExecutionMetadataHelper.IsCLanguage/IsCppLanguagealongside Python/JS, or better: always prefer_freePlayExecutorFactorywhen a non-C#languageis present in metadata, falling back toExecuteGeneralCodeAsynconly for the C#/unset default).Why not fixed alongside Phase 5 integration tests
Out of scope for a test-writing pass, and the in-process test fixture never registers the Clang executors anyway (needs wasi-sdk + wasmtime baked into the worker's Docker image), so this bug isn't observable from that fixture regardless - it was found by reading the dispatch code while designing the C/C++ coverage, not from a failing test.
Resolved in spikersoft-backend PR #178 (merged to
master). Added auseClangarm (keyed offCodeExecutionMetadataHelper.IsClangLanguage, free-play only) to the free-play dispatch inCodeExecutionWorkerService.ExecuteCodeAsync, so C/C++ submissions now reach the language-aware free-play factory (CFreePlayCodeExecutor/CppFreePlayCodeExecutor) instead of falling through to Roslyn C#.ExecuteNonCsharpFreePlayAsyncalready resolved the executor via_freePlayExecutorFactory.For(metadata), so no deeper change was needed. Keyed offmetadata.languagerather than a grading-runtime member sinceLessonGradingRuntimehas noClangC/ClangCpp. NewCodeExecutionWorkerServiceTeststheory (c,cpp) pins the routing;dotnet test SpikerSoft.Tests.Unitgreen. Closing.