Runner: Docker-Zeitlimit liefert sicher 124 nach rm -f
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
bcc0e42374
commit
12513b73c3
2 files changed
+47
-2
No files matched your search
@@ -139,6 +139,7 @@ export function createDocker({ exec = spawnDocker, baseEnv = process.env, envDir
|
|||||||
child.stdout?.on('data', (d) => split.push(String(d)));
|
child.stdout?.on('data', (d) => split.push(String(d)));
|
||||||
child.stderr?.on('data', (d) => split2.push(String(d)));
|
child.stderr?.on('data', (d) => split2.push(String(d)));
|
||||||
let done = false;
|
let done = false;
|
||||||
|
let timedOut = false;
|
||||||
let timer;
|
let timer;
|
||||||
const finish = (res) => {
|
const finish = (res) => {
|
||||||
if (done) return;
|
if (done) return;
|
||||||
@@ -148,10 +149,16 @@ export function createDocker({ exec = spawnDocker, baseEnv = process.env, envDir
|
|||||||
split.flush(); split2.flush();
|
split.flush(); split2.flush();
|
||||||
resolve(res);
|
resolve(res);
|
||||||
};
|
};
|
||||||
child.on('error', (e) => { if (!done) { done = true; clearTimeout(timer); envFile?.cleanup(); reject(e); } });
|
child.on('error', (e) => {
|
||||||
child.on('close', (code) => finish({ code: code ?? 1 }));
|
if (done) return;
|
||||||
|
if (timedOut) return; // Zeitlimit-Pfad löst selbst auf (124)
|
||||||
|
done = true; clearTimeout(timer); envFile?.cleanup(); reject(e);
|
||||||
|
});
|
||||||
|
child.on('close', (code) => { if (!timedOut) finish({ code: code ?? 1 }); });
|
||||||
if (timeoutMs > 0) {
|
if (timeoutMs > 0) {
|
||||||
timer = setTimeout(async () => {
|
timer = setTimeout(async () => {
|
||||||
|
if (done) return;
|
||||||
|
timedOut = true;
|
||||||
try { child.kill('SIGKILL'); } catch { /* schon beendet */ }
|
try { child.kill('SIGKILL'); } catch { /* schon beendet */ }
|
||||||
const name = optionName(args);
|
const name = optionName(args);
|
||||||
if (name) await forceRemove(name);
|
if (name) await forceRemove(name);
|
||||||
|
|||||||
@@ -169,3 +169,41 @@ test('rm/stop: ungültiger Name wird abgelehnt', async () => {
|
|||||||
await assert.rejects(docker.rm('--all'));
|
await assert.rejects(docker.rm('--all'));
|
||||||
await assert.rejects(docker.stop('a b'));
|
await assert.rejects(docker.stop('a b'));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Zeitlimit: close direkt nach kill ändert Ergebnis nicht, rm -f wird vor Auflösung abgewartet', async () => {
|
||||||
|
const events = [];
|
||||||
|
const child = fakeChild();
|
||||||
|
child.kill = (s) => { child.killed.push(s); setImmediate(() => child.emit('close', null)); };
|
||||||
|
const rmChild = fakeChild();
|
||||||
|
let calls = 0;
|
||||||
|
const docker = createDocker({ rmCapMs: 1000, exec: (args) => {
|
||||||
|
if (calls++ === 0) return child;
|
||||||
|
events.push('rm-start');
|
||||||
|
setTimeout(() => { events.push('rm-done'); rmChild.emit('close', 0); }, 40);
|
||||||
|
return rmChild;
|
||||||
|
} });
|
||||||
|
const r = await docker.run(['run', '--name', 'job-2', 'node:20', 'x'], { timeoutMs: 10 });
|
||||||
|
events.push('resolved');
|
||||||
|
assert.deepEqual(r, { code: 124 });
|
||||||
|
assert.deepEqual(events, ['rm-start', 'rm-done', 'resolved']);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('spawn-Fehler ⇒ env-file wird entfernt, run lehnt ab', async () => {
|
||||||
|
let filePath;
|
||||||
|
const child = fakeChild();
|
||||||
|
const docker = createDocker({ exec: (args) => { filePath = args[args.indexOf('--env-file') + 1]; return child; } });
|
||||||
|
const p = docker.run(['run', 'node:20'], { env: { K: 'v' } });
|
||||||
|
assert.equal(existsSync(filePath), true);
|
||||||
|
child.emit('error', new Error('ENOENT'));
|
||||||
|
await assert.rejects(p, /ENOENT/);
|
||||||
|
assert.equal(existsSync(filePath), false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Zeitlimit mit env-file: Datei wird entfernt', async () => {
|
||||||
|
let filePath;
|
||||||
|
const child = fakeChild();
|
||||||
|
child.kill = () => setImmediate(() => child.emit('close', null));
|
||||||
|
const docker = createDocker({ rmCapMs: 10, exec: (args) => { if (args[0] === 'run') { filePath = args[args.indexOf('--env-file') + 1]; return child; } return fakeChild(); } });
|
||||||
|
assert.deepEqual(await docker.run(['run', '--name', 'j', 'node:20'], { env: { K: 'v' }, timeoutMs: 10 }), { code: 124 });
|
||||||
|
assert.equal(existsSync(filePath), false);
|
||||||
|
});
|
||||||
Reference in new issue
Block a user