Upload via GUI (39 Dateien)
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
'use strict';
|
||||
|
||||
const DEFAULT_GRACE_MS = 15000;
|
||||
|
||||
const CLEAN_SHUTDOWN = /\[(?:Render thread|Client thread)\/INFO\](?:\s+\([^)]*\))?:\s*Stopping!\s*$/;
|
||||
const FATAL_OUTPUT = [
|
||||
/---- Minecraft Crash Report ----/i,
|
||||
/\b(?:Encountered an unexpected exception|Unreported exception thrown|Reported exception thrown)\b/i,
|
||||
/\b(?:This crash report has been saved to|Saving crash report to)\b/i,
|
||||
/\bA fatal error has been detected by the Java Runtime Environment\b/i,
|
||||
/Exception in thread "(?:Render thread|Client thread|main)"/i,
|
||||
/\[(?:Render thread|Client thread|main)\/FATAL\]/i,
|
||||
];
|
||||
|
||||
function createProcessWatchdog(options) {
|
||||
const graceMs = options.graceMs || DEFAULT_GRACE_MS;
|
||||
const schedule = options.setTimer || setTimeout;
|
||||
const cancel = options.clearTimer || clearTimeout;
|
||||
const buffers = { stdout: '', stderr: '' };
|
||||
let timer = null;
|
||||
let armed = false;
|
||||
let crashed = false;
|
||||
let ended = false;
|
||||
let forced = false;
|
||||
// bleibt true, sobald einmal ein regulärer Shutdown ("Stopping!") gesehen
|
||||
// wurde – im Gegensatz zu `armed` wird das NICHT durch markCrash()
|
||||
// zurückgesetzt, damit ein später vom internen Watchdog erzwungener Halt
|
||||
// weiterhin als "war ein regulärer Shutdown" erkennbar bleibt
|
||||
let sawCleanShutdown = false;
|
||||
|
||||
function clear() {
|
||||
if (timer !== null) cancel(timer);
|
||||
timer = null;
|
||||
armed = false;
|
||||
}
|
||||
|
||||
function markCrash() {
|
||||
crashed = true;
|
||||
clear();
|
||||
}
|
||||
|
||||
function scheduleKill() {
|
||||
if (timer !== null) cancel(timer);
|
||||
timer = schedule(() => {
|
||||
timer = null;
|
||||
if (ended || crashed || !armed || !options.isRunning()) return;
|
||||
try {
|
||||
forced = options.kill() === true;
|
||||
} catch {
|
||||
forced = false;
|
||||
}
|
||||
if (forced && options.onForce) options.onForce(graceMs);
|
||||
else if (!forced && options.isRunning() && options.onError) options.onError();
|
||||
}, graceMs);
|
||||
if (timer && typeof timer.unref === 'function') timer.unref();
|
||||
}
|
||||
|
||||
function inspectLine(line) {
|
||||
const isCleanShutdown = CLEAN_SHUTDOWN.test(line);
|
||||
if (isCleanShutdown) sawCleanShutdown = true;
|
||||
if (FATAL_OUTPUT.some((pattern) => pattern.test(line))) {
|
||||
markCrash();
|
||||
return;
|
||||
}
|
||||
if (ended || crashed || armed || !isCleanShutdown) return;
|
||||
|
||||
armed = true;
|
||||
scheduleKill();
|
||||
}
|
||||
|
||||
function feed(chunk, stream) {
|
||||
if (ended) return;
|
||||
const key = stream === 'stderr' ? 'stderr' : 'stdout';
|
||||
const text = buffers[key] + String(chunk || '');
|
||||
const lines = text.split(/\r?\n/);
|
||||
buffers[key] = lines.pop() || '';
|
||||
for (const line of lines) inspectLine(line);
|
||||
if (armed && !crashed && !ended && lines.length) scheduleKill();
|
||||
}
|
||||
|
||||
function end() {
|
||||
ended = true;
|
||||
clear();
|
||||
}
|
||||
|
||||
return {
|
||||
feed,
|
||||
end,
|
||||
get armed() { return armed; },
|
||||
get crashed() { return crashed; },
|
||||
get forced() { return forced; },
|
||||
get sawCleanShutdown() { return sawCleanShutdown; },
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
DEFAULT_GRACE_MS,
|
||||
CLEAN_SHUTDOWN,
|
||||
FATAL_OUTPUT,
|
||||
createProcessWatchdog,
|
||||
};
|
||||
Reference in New Issue
Block a user