File size: 2,671 Bytes
8be86f8
 
 
 
 
 
 
 
 
f79700a
 
 
8be86f8
 
 
 
 
 
f79700a
 
8be86f8
 
 
f79700a
 
8be86f8
 
 
 
 
 
 
 
f79700a
 
8be86f8
f79700a
8be86f8
 
 
 
 
 
 
f79700a
8be86f8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f79700a
 
8be86f8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
import os
import re
import shutil
import subprocess
import tempfile
import uuid
import resource
import time

MAX_CODE_SIZE = 50_000       # 50 KB max user code
MAX_EXECUTION_TIME = 5        # 5 seconds max execution
JAVA_HEAP_LIMIT = "1024m"     # 1 GB max heap for Java user code

def extract_class_name(code: str) -> str:
    match = re.search(r'public\s+class\s+(\w+)', code)
    return match.group(1) if match else "Main"

def set_limits():
    # Limit only CPU time; no artificial memory limit
    import resource
    resource.setrlimit(resource.RLIMIT_CPU, (MAX_EXECUTION_TIME, MAX_EXECUTION_TIME))

def run_java(code: str):
    import os, tempfile, subprocess, uuid, shutil, time, re

    if len(code.encode("utf-8")) > MAX_CODE_SIZE:
        return {"status": "error", "message": "Code too large"}

    run_id = str(uuid.uuid4())
    workdir = os.path.join(tempfile.gettempdir(), f"runner_{run_id}")
    os.makedirs(workdir, exist_ok=True)

    try:
        class_name = re.search(r'public\s+class\s+(\w+)', code)
        class_name = class_name.group(1) if class_name else "Main"

        java_file = os.path.join(workdir, f"{class_name}.java")
        with open(java_file, "w") as f:
            f.write(code)

        # Compile
        start_compile = time.time()
        compile_proc = subprocess.run(
            ["javac", java_file],
            capture_output=True, text=True, cwd=workdir
        )
        compile_time = (time.time() - start_compile) * 1000
        if compile_proc.returncode != 0:
            return {
                "status": "error",
                "stage": "compile",
                "compile_time_ms": round(compile_time, 2),
                "exit_code": compile_proc.returncode,
                "stdout": compile_proc.stdout,
                "stderr": compile_proc.stderr
            }

        # Run
        start_run = time.time()
        run_proc = subprocess.run(
            ["java", f"-Xmx{JAVA_HEAP_LIMIT}", "-cp", workdir, class_name],
            capture_output=True, text=True,
            cwd=workdir,
            timeout=MAX_EXECUTION_TIME,
            preexec_fn=set_limits
        )
        run_time = (time.time() - start_run) * 1000

        return {
            "status": "success",
            "compile_time_ms": round(compile_time, 2),
            "execution_time_ms": round(run_time, 2),
            "exit_code": run_proc.returncode,
            "stdout": run_proc.stdout,
            "stderr": run_proc.stderr
        }

    except subprocess.TimeoutExpired:
        return {"status": "error", "stage": "run", "message": "Execution timed out"}

    finally:
        shutil.rmtree(workdir, ignore_errors=True)