bitburner-src/src/Netscript/killWorkerScript.ts

133 lines
4.1 KiB
TypeScript
Raw Normal View History

/**
* Stops an actively-running script (represented by a WorkerScript object)
* and removes it from the global pool of active scripts.
*/
import { ScriptDeath } from "./ScriptDeath";
import { WorkerScript } from "./WorkerScript";
import { workerScripts } from "./WorkerScripts";
import { WorkerScriptStartStopEventEmitter } from "./WorkerScriptStartStopEventEmitter";
import { RunningScript } from "../Script/RunningScript";
2021-10-07 22:56:01 +02:00
import { GetServer } from "../Server/AllServers";
2021-10-15 02:13:26 +02:00
import { dialogBoxCreate } from "../ui/React/DialogBox";
import { AddRecentScript } from "./RecentScripts";
2021-11-16 05:49:33 +01:00
import { Player } from "../Player";
2022-07-20 07:48:54 +02:00
export type killScriptParams = WorkerScript | number | { runningScript: RunningScript; hostname: string };
2021-09-05 01:09:30 +02:00
2022-07-20 07:48:54 +02:00
export function killWorkerScript(params: killScriptParams): boolean {
if (params instanceof WorkerScript) {
stopAndCleanUpWorkerScript(params);
2021-09-05 01:09:30 +02:00
return true;
2022-07-20 07:48:54 +02:00
} else if (typeof params === "number") {
return killWorkerScriptByPid(params);
} else {
2021-09-05 01:09:30 +02:00
// Try to kill by PID
2022-07-20 07:48:54 +02:00
const res = killWorkerScriptByPid(params.runningScript.pid);
2021-09-05 01:09:30 +02:00
if (res) {
return res;
}
2021-09-05 01:09:30 +02:00
// If for some reason that doesn't work, we'll try the old way
for (const ws of workerScripts.values()) {
2022-08-07 17:40:42 +02:00
if (ws.scriptRef === params.runningScript) {
2022-07-20 07:48:54 +02:00
stopAndCleanUpWorkerScript(ws);
return true;
2021-09-05 01:09:30 +02:00
}
}
2021-09-05 01:09:30 +02:00
return false;
}
}
2022-07-20 07:48:54 +02:00
function killWorkerScriptByPid(pid: number): boolean {
2021-09-05 01:09:30 +02:00
const ws = workerScripts.get(pid);
if (ws instanceof WorkerScript) {
2022-07-20 07:48:54 +02:00
stopAndCleanUpWorkerScript(ws);
2021-09-05 01:09:30 +02:00
return true;
}
2021-09-05 01:09:30 +02:00
return false;
}
function stopAndCleanUpWorkerScript(ws: WorkerScript): void {
killNetscriptDelay(ws);
if (typeof ws.atExit === "function") {
2021-10-15 02:13:26 +02:00
try {
ws.env.stopFlag = false;
ws.atExit();
2022-07-15 07:51:30 +02:00
} catch (e: unknown) {
let message = e instanceof ScriptDeath ? e.errorMessage : String(e);
message = message.replace(/.*\|DELIMITER\|/, "");
2021-10-15 02:13:26 +02:00
dialogBoxCreate(
2022-08-17 02:37:50 +02:00
`Error trying to call atExit for script ${[ws.name, ...ws.args].join(" ")} on ${ws.hostname}\n ${message}`,
2021-10-15 02:13:26 +02:00
);
2022-08-23 17:28:40 +02:00
console.error(e);
2021-10-15 02:13:26 +02:00
}
ws.atExit = undefined;
2021-10-15 02:13:26 +02:00
}
ws.env.stopFlag = true;
removeWorkerScript(ws);
}
/**
* Helper function that removes the script being killed from the global pool.
* Also handles other cleanup-time operations
*
* @param {WorkerScript} - Identifier for WorkerScript. Either the object itself, or
* its index in the global workerScripts array
*/
2022-07-20 07:48:54 +02:00
function removeWorkerScript(workerScript: WorkerScript): void {
const ip = workerScript.hostname;
2021-09-05 01:09:30 +02:00
// Get the server on which the script runs
const server = GetServer(ip);
if (server == null) {
console.error(`Could not find server on which this script is running: ${ip}`);
return;
}
// Delete the RunningScript object from that server
for (let i = 0; i < server.runningScripts.length; ++i) {
const runningScript = server.runningScripts[i];
2022-08-07 17:40:42 +02:00
if (runningScript === workerScript.scriptRef) {
server.runningScripts.splice(i, 1);
break;
2021-09-05 01:09:30 +02:00
}
}
2021-09-05 01:09:30 +02:00
// Recalculate ram used on that server
2021-11-16 05:49:33 +01:00
server.updateRamUsed(0, Player);
for (const rs of server.runningScripts) server.updateRamUsed(server.ramUsed + rs.ramUsage * rs.threads, Player);
2021-10-09 05:45:54 +02:00
// Delete script from global pool (workerScripts)
2021-12-03 22:21:35 +01:00
workerScripts.delete(workerScript.pid);
// const res = workerScripts.delete(workerScript.pid);
// if (!res) {
// console.warn(`removeWorkerScript() called with WorkerScript that wasn't in the global map:`);
// console.warn(workerScript);
// }
AddRecentScript(workerScript);
2021-09-05 01:09:30 +02:00
2022-07-20 07:48:54 +02:00
WorkerScriptStartStopEventEmitter.emit();
}
/**
* Helper function that interrupts a script's delay if it is in the middle of a
* timed, blocked operation (like hack(), sleep(), etc.). This allows scripts to
* be killed immediately even if they're in the middle of one of those long operations
*/
2021-05-01 09:17:31 +02:00
function killNetscriptDelay(workerScript: WorkerScript): void {
2021-09-05 01:09:30 +02:00
if (workerScript instanceof WorkerScript) {
if (workerScript.delay) {
clearTimeout(workerScript.delay);
if (workerScript.delayReject) {
workerScript.delayReject(new ScriptDeath(workerScript));
2021-09-05 01:09:30 +02:00
}
}
2021-09-05 01:09:30 +02:00
}
}