-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathexecutor.js
More file actions
74 lines (60 loc) · 2.32 KB
/
executor.js
File metadata and controls
74 lines (60 loc) · 2.32 KB
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
const { getContainer, docker, languages, releaseContainer } = require("./containerManager");
async function executeCodeInContainer(language, code, input) {
const container = await getContainer(language);
const { extension, interpreted, compileCmd, runCmd, command } = languages[language];
try {
const filePath = `/code/Main.${extension}`;
const safeCode = code.replace(/'/g, "'\\''");
const writeCodeCmd = `echo '${safeCode}' > ${filePath}`;
let finalCommand = interpreted ? command : `${compileCmd} && ${runCmd}`;
const exec = await container.exec({
AttachStdout: true,
AttachStderr: true,
AttachStdin: !!input,
Tty: false,
Cmd: ["/bin/sh", "-c", `${writeCodeCmd} && ${finalCommand}`],
});
return new Promise((resolve, reject) => {
exec.start({ hijack: true, stdin: !!input }, (err, stream) => {
if (err) return reject({ success: false, error: `Execution failed: ${err.message}` });
let outputBuffers = [];
let errorBuffers = [];
docker.modem.demuxStream(
stream,
{ write: (chunk) => outputBuffers.push(chunk) },
{ write: (chunk) => errorBuffers.push(chunk) }
);
const startTime = Date.now();
stream.on("error", (error) => {
reject({ success: false, error: `Stream error: ${error.message}` });
});
if (input) {
stream.write(input + "\n");
}
stream.on("end", () => {
const executionTime = Date.now() - startTime;
const output = Buffer.concat(outputBuffers).toString().trim();
const error = Buffer.concat(errorBuffers).toString().trim();
resolve({
success: error.length === 0,
output,
error,
executionTime,
});
});
stream.on("close", () => {
if (outputBuffers.length === 0 && errorBuffers.length === 0) {
reject({ success: false, error: "No output received, possible execution failure." });
}
});
});
});
} catch (error) {
return { success: false, error: `Execution failed: ${error.message}` };
} finally {
releaseContainer(language, container.id);
}
}
module.exports = {
executeCodeInContainer,
};