theguywhosucks commited on
Commit
ee157b2
·
verified ·
1 Parent(s): bcd5752

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +111 -0
app.py ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import uuid
3
+ import subprocess
4
+ import resource
5
+ import multiprocessing
6
+ import signal
7
+ import time
8
+ from fastapi import FastAPI, HTTPException
9
+ from fastapi.middleware.cors import CORSMiddleware
10
+ import uvicorn
11
+
12
+ # --- FastAPI app ---
13
+ app = FastAPI()
14
+
15
+ # Allow CORS for frontend testing (optional)
16
+ app.add_middleware(
17
+ CORSMiddleware,
18
+ allow_origins=["*"],
19
+ allow_credentials=True,
20
+ allow_methods=["*"],
21
+ allow_headers=["*"],
22
+ )
23
+
24
+ # Store running sandboxes
25
+ sandboxes = {}
26
+
27
+ # --- Sandbox worker ---
28
+ def sandbox_worker(sandbox_id: str, code: str):
29
+ user_dir = f"/tmp/sandbox_{sandbox_id}"
30
+ os.makedirs(user_dir, exist_ok=True)
31
+ os.chdir(user_dir)
32
+
33
+ # Resource limits
34
+ resource.setrlimit(resource.RLIMIT_AS, (4 * 1024**3, 4 * 1024**3)) # 4GB RAM
35
+ resource.setrlimit(resource.RLIMIT_CPU, (7200, 7200)) # 2h CPU time
36
+
37
+ # Save user code
38
+ code_file = os.path.join(user_dir, "user_code.py")
39
+ with open(code_file, "w") as f:
40
+ f.write(code)
41
+
42
+ # Run code
43
+ try:
44
+ result = subprocess.run(
45
+ ["python3", code_file],
46
+ capture_output=True,
47
+ text=True,
48
+ timeout=7200 # 2h wall clock
49
+ )
50
+ # Save logs
51
+ with open(os.path.join(user_dir, "stdout.log"), "w") as f:
52
+ f.write(result.stdout)
53
+ with open(os.path.join(user_dir, "stderr.log"), "w") as f:
54
+ f.write(result.stderr)
55
+ except subprocess.TimeoutExpired:
56
+ with open(os.path.join(user_dir, "stderr.log"), "w") as f:
57
+ f.write("Execution timed out (2h limit reached).")
58
+
59
+
60
+ # --- API endpoints ---
61
+ @app.post("/launch")
62
+ def launch_sandbox(code: str):
63
+ sandbox_id = str(uuid.uuid4())[:8]
64
+
65
+ p = multiprocessing.Process(target=sandbox_worker, args=(sandbox_id, code))
66
+ p.start()
67
+
68
+ sandboxes[sandbox_id] = {"pid": p.pid, "start_time": time.time()}
69
+ return {"sandbox_id": sandbox_id}
70
+
71
+
72
+ @app.get("/logs/{sandbox_id}")
73
+ def get_logs(sandbox_id: str):
74
+ user_dir = f"/tmp/sandbox_{sandbox_id}"
75
+ if not os.path.exists(user_dir):
76
+ raise HTTPException(status_code=404, detail="Sandbox not found")
77
+
78
+ stdout_file = os.path.join(user_dir, "stdout.log")
79
+ stderr_file = os.path.join(user_dir, "stderr.log")
80
+
81
+ stdout = open(stdout_file).read() if os.path.exists(stdout_file) else ""
82
+ stderr = open(stderr_file).read() if os.path.exists(stderr_file) else ""
83
+
84
+ return {"stdout": stdout, "stderr": stderr}
85
+
86
+
87
+ @app.post("/kill/{sandbox_id}")
88
+ def kill_sandbox(sandbox_id: str):
89
+ if sandbox_id not in sandboxes:
90
+ raise HTTPException(status_code=404, detail="Sandbox not found")
91
+
92
+ pid = sandboxes[sandbox_id]["pid"]
93
+ try:
94
+ os.kill(pid, signal.SIGKILL)
95
+ del sandboxes[sandbox_id]
96
+ return {"status": "killed"}
97
+ except Exception as e:
98
+ raise HTTPException(status_code=500, detail=str(e))
99
+
100
+
101
+ @app.get("/status/{sandbox_id}")
102
+ def status(sandbox_id: str):
103
+ if sandbox_id not in sandboxes:
104
+ return {"status": "not found"}
105
+ elapsed = time.time() - sandboxes[sandbox_id]["start_time"]
106
+ return {"status": "running", "elapsed_sec": elapsed}
107
+
108
+
109
+ # --- Main entrypoint ---
110
+ if __name__ == "__main__":
111
+ uvicorn.run("app:app", host="0.0.0.0", port=8000, reload=True)