mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-12-25 07:32:27 +01:00
Merge pull request #3624 from danielyxie/infinite-loop-safety
MISC: Implemented infinite loop safety net.
This commit is contained in:
commit
f86eae5276
@ -84,6 +84,7 @@ export const CONSTANTS: {
|
|||||||
SoARepMult: number;
|
SoARepMult: number;
|
||||||
EntropyEffect: number;
|
EntropyEffect: number;
|
||||||
TotalNumBitNodes: number;
|
TotalNumBitNodes: number;
|
||||||
|
InfiniteLoopLimit: number;
|
||||||
Donations: number; // number of blood/plasma/palette donation the dev have verified., boosts NFG
|
Donations: number; // number of blood/plasma/palette donation the dev have verified., boosts NFG
|
||||||
LatestUpdate: string;
|
LatestUpdate: string;
|
||||||
} = {
|
} = {
|
||||||
@ -226,6 +227,8 @@ export const CONSTANTS: {
|
|||||||
// BitNode/Source-File related stuff
|
// BitNode/Source-File related stuff
|
||||||
TotalNumBitNodes: 24,
|
TotalNumBitNodes: 24,
|
||||||
|
|
||||||
|
InfiniteLoopLimit: 1000,
|
||||||
|
|
||||||
Donations: 7,
|
Donations: 7,
|
||||||
|
|
||||||
LatestUpdate: `
|
LatestUpdate: `
|
||||||
|
@ -179,6 +179,12 @@ export const CurrentOptionsPage = (props: IProps): React.ReactElement => {
|
|||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
<OptionSwitch
|
||||||
|
checked={Settings.InfinityLoopSafety}
|
||||||
|
onChange={(newValue) => (Settings.InfinityLoopSafety = newValue)}
|
||||||
|
text="Script infinite loop safety net"
|
||||||
|
tooltip={<>If this is set the game will attempt to automatically kill scripts stuck in infinite loops.</>}
|
||||||
|
/>
|
||||||
</GameOptionsPage>
|
</GameOptionsPage>
|
||||||
),
|
),
|
||||||
[GameOptionsTab.INTERFACE]: (
|
[GameOptionsTab.INTERFACE]: (
|
||||||
|
@ -5,6 +5,8 @@ import type { WorkerScript } from "./WorkerScript";
|
|||||||
import { makeRuntimeRejectMsg } from "../NetscriptEvaluator";
|
import { makeRuntimeRejectMsg } from "../NetscriptEvaluator";
|
||||||
import { Player } from "../Player";
|
import { Player } from "../Player";
|
||||||
import { CityName } from "src/Locations/data/CityNames";
|
import { CityName } from "src/Locations/data/CityNames";
|
||||||
|
import { Settings } from "../Settings/Settings";
|
||||||
|
import { CONSTANTS } from "../Constants";
|
||||||
|
|
||||||
type ExternalFunction = (...args: any[]) => any;
|
type ExternalFunction = (...args: any[]) => any;
|
||||||
type ExternalAPI = {
|
type ExternalAPI = {
|
||||||
@ -91,8 +93,14 @@ function wrapFunction(
|
|||||||
getValidPort: (port: any) => helpers.getValidPort(functionPath, port),
|
getValidPort: (port: any) => helpers.getValidPort(functionPath, port),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
const safetyEnabled = Settings.InfinityLoopSafety;
|
||||||
function wrappedFunction(...args: unknown[]): unknown {
|
function wrappedFunction(...args: unknown[]): unknown {
|
||||||
helpers.updateDynamicRam(ctx.function, getRamCost(Player, ...tree, ctx.function));
|
helpers.updateDynamicRam(ctx.function, getRamCost(Player, ...tree, ctx.function));
|
||||||
|
if (safetyEnabled) workerScript.infiniteLoopSafetyCounter++;
|
||||||
|
if (workerScript.infiniteLoopSafetyCounter > CONSTANTS.InfiniteLoopLimit)
|
||||||
|
throw new Error(
|
||||||
|
`Infinite loop without sleep detected. ${CONSTANTS.InfiniteLoopLimit} ns functions were called without sleep. This will cause your UI to hang.`,
|
||||||
|
);
|
||||||
return func(ctx)(...args);
|
return func(ctx)(...args);
|
||||||
}
|
}
|
||||||
const parent = getNestedProperty(wrappedAPI, ...tree);
|
const parent = getNestedProperty(wrappedAPI, ...tree);
|
||||||
|
@ -111,6 +111,11 @@ export class WorkerScript {
|
|||||||
*/
|
*/
|
||||||
atExit: any;
|
atExit: any;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Once this counter reaches it's limit the script crashes. It is reset when a promise completes.
|
||||||
|
*/
|
||||||
|
infiniteLoopSafetyCounter = 0;
|
||||||
|
|
||||||
constructor(runningScriptObj: RunningScript, pid: number, nsFuncsGenerator?: (ws: WorkerScript) => any) {
|
constructor(runningScriptObj: RunningScript, pid: number, nsFuncsGenerator?: (ws: WorkerScript) => any) {
|
||||||
this.name = runningScriptObj.filename;
|
this.name = runningScriptObj.filename;
|
||||||
this.hostname = runningScriptObj.server;
|
this.hostname = runningScriptObj.server;
|
||||||
|
@ -14,6 +14,7 @@ export function netscriptDelay(time: number, workerScript: WorkerScript): Promis
|
|||||||
workerScript.delay = null;
|
workerScript.delay = null;
|
||||||
workerScript.delayReject = undefined;
|
workerScript.delayReject = undefined;
|
||||||
|
|
||||||
|
workerScript.infiniteLoopSafetyCounter = 0;
|
||||||
if (workerScript.env.stopFlag) reject(new ScriptDeath(workerScript));
|
if (workerScript.env.stopFlag) reject(new ScriptDeath(workerScript));
|
||||||
else resolve();
|
else resolve();
|
||||||
}, time);
|
}, time);
|
||||||
|
@ -54,6 +54,11 @@ interface IDefaultSettings {
|
|||||||
*/
|
*/
|
||||||
EnableBashHotkeys: boolean;
|
EnableBashHotkeys: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Infinite loop safety net
|
||||||
|
*/
|
||||||
|
InfinityLoopSafety: boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Timestamps format
|
* Timestamps format
|
||||||
*/
|
*/
|
||||||
@ -201,6 +206,7 @@ export const defaultSettings: IDefaultSettings = {
|
|||||||
DisableOverviewProgressBars: false,
|
DisableOverviewProgressBars: false,
|
||||||
EnableBashHotkeys: false,
|
EnableBashHotkeys: false,
|
||||||
TimestampsFormat: "",
|
TimestampsFormat: "",
|
||||||
|
InfinityLoopSafety: true,
|
||||||
Locale: "en",
|
Locale: "en",
|
||||||
MaxRecentScriptsCapacity: 50,
|
MaxRecentScriptsCapacity: 50,
|
||||||
MaxLogCapacity: 50,
|
MaxLogCapacity: 50,
|
||||||
@ -241,6 +247,7 @@ export const Settings: ISettings & ISelfInitializer & ISelfLoading = {
|
|||||||
DisableOverviewProgressBars: defaultSettings.DisableOverviewProgressBars,
|
DisableOverviewProgressBars: defaultSettings.DisableOverviewProgressBars,
|
||||||
EnableBashHotkeys: defaultSettings.EnableBashHotkeys,
|
EnableBashHotkeys: defaultSettings.EnableBashHotkeys,
|
||||||
TimestampsFormat: defaultSettings.TimestampsFormat,
|
TimestampsFormat: defaultSettings.TimestampsFormat,
|
||||||
|
InfinityLoopSafety: defaultSettings.InfinityLoopSafety,
|
||||||
Locale: "en",
|
Locale: "en",
|
||||||
MaxRecentScriptsCapacity: defaultSettings.MaxRecentScriptsCapacity,
|
MaxRecentScriptsCapacity: defaultSettings.MaxRecentScriptsCapacity,
|
||||||
MaxLogCapacity: defaultSettings.MaxLogCapacity,
|
MaxLogCapacity: defaultSettings.MaxLogCapacity,
|
||||||
|
Loading…
Reference in New Issue
Block a user