Skip to content

Fix code execution failing on serverless read-only filesystem - #62

Open
umarjaved204 wants to merge 1 commit into
QuantumLogicsLabs:mainfrom
umarjaved204:fix/cpp-execution-serverless
Open

umarjaved204 wants to merge 1 commit into
QuantumLogicsLabs:mainfrom
umarjaved204:fix/cpp-execution-serverless

Conversation

@umarjaved204

Copy link
Copy Markdown

Problem

C++ execution has never worked on the deployed backend. POST /api/challenges/run-cpp returns HTTP 500 in production:

{"stdout":"","stderr":"ENOENT: no such file or directory, mkdir '/var/task/src/runtime'","error":"...","exitCode":1}

executeCppCode created its temp directory at RUNTIME_TMP_PATH, which resolves to /var/task/src/runtime/tmp — inside the deployment bundle, which Vercel mounts read-only. The request died at mkdir, before any compiler was invoked.

executeJavaScriptCode and executeJavaCode had the identical bug.

Fix

Use the existing getWritableRuntimeDir() helper, which falls back to os.tmpdir() on serverless. executeRubyCode already did this; the other three didn't.

Also included:

  • executeCppViaPiston() — remote compile fallback for hosts with no local g++, mirroring the existing executeRubyViaPiston(). Dormant unless PISTON_API_URL is configured.
  • Honest error message — the old one said "install MinGW/g++", which isn't actionable on a managed host.
  • Cleanup fix — compile failures now delete the binary, not just the source. This was leaking files.
  • nodemon ignores src/runtime/tmp — writing a temp file was restarting the dev server and killing the in-flight request. This is also why stale run_*.cpp files ended up committed under src/runtime/tmp/.

Testing

Verified locally (PowerShell, where the MSYS2 g++ resolves correctly):

POST /api/challenges/run-cpp
  cout << "Score: " << x << endl;  cout << 3 + 4 << endl;

→ {"stdout":"Score: 100\r\n7","stderr":"","error":null,"exitCode":0}

Ran 3× consecutively — no temp files left behind. Serverless code path verified separately with VERCEL=1.

What this does NOT fix

C++ still will not run on Vercel after this merges, because that runtime ships no C++ compiler and one cannot be installed there. This PR fixes the crash and makes the failure report itself honestly.

Making C++ actually execute in production additionally requires a compiler, via either:

  1. PISTON_API_URL pointed at a self-hosted Piston instance (sandboxed; no code change needed — just the env var), or
  2. Moving code execution to a non-serverless host where g++ can be installed.

This needs a decision from whoever owns deployment.

Note: the public Piston API — the current default value — went whitelist-only on 2026-02-15, so the existing Ruby fallback is also non-functional for the same reason.

Security note

Code execution here is unsandboxed — a timeout is the only limit, with no memory, filesystem, or network restrictions. This PR neither introduces nor fixes that, but it's worth confirming the team is comfortable with it before C++ execution goes live, given the input is user-submitted. Self-hosted Piston would address it.

Related frontend issue (separate repo)

Why this went unnoticed for so long: runCpp.js catches the 500, keyword-matches it as "compiler unavailable" (the regex /g\+\+|compiler.*not|not installed|enoent/i matches our ENOENT text), substitutes a browser simulation that only prints quoted string literals, and then stripSimulationBanner() deletes the "simulation mode" warning before rendering the result as a successful run.

Net effect: cout << "Score: " << 100 << endl; displays Score: — the literal survives, the variable silently vanishes, and nothing indicates it wasn't really executed.

To be filed separately against PolyCode-Frontend. The Playground already handles this correctly (playgroundExecutor.js prepends a visible "simulation only" warning), and Java lessons rethrow properly — C++ is the outlier.

executeCppCode, executeJavaScriptCode and executeJavaCode created their temp
directory at RUNTIME_TMP_PATH, which resolves inside the deployment bundle.
On Vercel that path is read-only, so every request failed with
"ENOENT: no such file or directory, mkdir '/var/task/src/runtime'" before a
compiler was ever invoked.

They now use the existing getWritableRuntimeDir() helper, which falls back to
os.tmpdir() on serverless -- the same approach executeRubyCode already took.

Also in this change:
- Add executeCppViaPiston() so hosts without a local g++ can compile remotely,
  mirroring the existing executeRubyViaPiston(). Dormant unless PISTON_API_URL
  points at a reachable instance.
- Replace the "install MinGW/g++" error, which is not actionable on a managed
  host, with one naming the actual configuration needed.
- Delete the compiled binary when compilation fails; only the source was being
  cleaned up.
- Tell nodemon to ignore src/runtime/tmp, so writing a temp file no longer
  restarts the dev server and kills the in-flight request.

Note: C++ still cannot execute on Vercel after this change, because that
runtime ships no C++ compiler. This fixes the crash and makes the failure
report itself honestly; running C++ in production additionally requires a
compiler, via PISTON_API_URL or a non-serverless host.
@vercel

vercel Bot commented Sep 12, 2026

Copy link
Copy Markdown

@umarjaved204 is attempting to deploy a commit to the seno-quantum-coder's projects Team on Vercel.

A member of the Team first needs to authorize it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant