Skip to content

Instantly share code, notes, and snippets.

@jasonLaster
Created January 28, 2021 23:24
Show Gist options
  • Select an option

  • Save jasonLaster/14b8fe54ad2f4f53df95131e1f8f8757 to your computer and use it in GitHub Desktop.

Select an option

Save jasonLaster/14b8fe54ad2f4f53df95131e1f8f8757 to your computer and use it in GitHub Desktop.
diff --git a/src/control/child.ts b/src/control/child.ts
index cbf54089..25fbf35d 100644
--- a/src/control/child.ts
+++ b/src/control/child.ts
@@ -288,12 +288,6 @@ export class Child {
}
}
-// Map ID -> Process for all processes that exist and haven't crashed.
-const gProcesses: Map<number, Process> = new Map();
-
-// Processes that are currently unpaused.
-const gUnpausedProcesses: Set<Process> = new Set();
-
// State used to watch for hanged children.
const PingIntervalMs = 2000;
const MaxStalledPings = 10;
@@ -366,10 +360,10 @@ class Process {
startManifest(manifest: Manifest, index: number) {
assert(!this.terminated);
- if (!gUnpausedProcesses.has(this)) {
+ if (!this.unpausedProcesses.has(this)) {
this.pings.length = 0;
this.lastPingTime = Date.now();
- gUnpausedProcesses.add(this);
+ this.unpausedProcesses.add(this);
}
this.pending.push({ manifest, index, time: Date.now(), result: null });
@@ -584,30 +578,6 @@ export function newRootChild() {
return new Child("Root", FirstCheckpointExecutionPoint, processId);
}
-export function ManifestFinished(processId: number, index: number, result = {}) {
- try {
- const process = gProcesses.get(processId);
- if (process) {
- process.onManifestFinished(index, result);
- }
- } catch (e) {
- logException(e);
- }
-}
-
-export function UnhandledDivergence(processId: number, index: number) {
- try {
- const process = gProcesses.get(processId);
- if (process) {
- process.onManifestFinished(index, {
- failed: ManifestFailedReason.UnhandledDivergence,
- });
- }
- } catch (e) {
- logException(e);
- }
-}
-
export function PingResponse(processId: number, pingId: number, progress: number) {
try {
const process = gProcesses.get(processId);
@@ -697,73 +667,104 @@ function respawnCrashedProcess(process: Process) {
const MaxCrashes = 20;
let gNumCrashes = 0;
-// Get the IDs of all processes which are due to be forked from processId.
-function getTransitiveForks(processId: number): number[] {
- const process = gProcesses.get(processId);
- if (!process) {
- return [];
- }
+class Processes {
+ // Map ID -> Process for all processes that exist and haven't crashed.
+ processes: Map<number, Process> = new Map();
+
+ // Processes that are currently unpaused.
+ unpausedProcesses: Set<Process> = new Set();
- const rv = [];
- for (const { manifest } of process.pending) {
- if (manifest.kind == "fork") {
- rv.push(manifest.id, ...getTransitiveForks(manifest.id));
+ ManifestFinished(processId: number, index: number, result = {}) {
+ try {
+ const process = this.processes.get(processId);
+ if (process) {
+ process.onManifestFinished(index, result);
+ }
+ } catch (e) {
+ logException(e);
}
}
- return rv;
-}
-export function RecoverFromCrash(processId: number) {
- const process = gProcesses.get(processId);
- if (!process) {
- return;
+ UnhandledDivergence(processId: number, index: number) {
+ try {
+ const process = this.processes.get(processId);
+ if (process) {
+ process.onManifestFinished(index, {
+ failed: ManifestFailedReason.UnhandledDivergence,
+ });
+ }
+ } catch (e) {
+ logException(e);
+ }
}
+ // Get the IDs of all processes which are due to be forked from processId.
+ getTransitiveForks(processId: number): number[] {
+ const process = this.processes.get(processId);
+ if (!process) {
+ return [];
+ }
- if (processId == ServerProcessId) {
- // We can't recover from server process crashes. Trigger a fatal error
- // soon, so that we have time to download symbols. This isn't ideal,
- // it would be nice if we could notify the dispatcher that we have failed
- // without closing the connection.
- setTimeout(() => Channel.fatalError("Server process crashed"), MsPerSecond * 10);
- return;
+ const rv = [];
+ for (const { manifest } of process.pending) {
+ if (manifest.kind == "fork") {
+ rv.push(manifest.id, ...this.getTransitiveForks(manifest.id));
+ }
+ }
+ return rv;
}
- if (!LinkerProcess.shouldRespawnChildren()) {
- return;
- }
+ RecoverFromCrash(processId: number) {
+ const process = this.processes.get(processId);
+ if (!process) {
+ return;
+ }
- process.logger.error("RecoverFromCrash");
+ if (processId == ServerProcessId) {
+ // We can't recover from server process crashes. Trigger a fatal error
+ // soon, so that we have time to download symbols. This isn't ideal,
+ // it would be nice if we could notify the dispatcher that we have failed
+ // without closing the connection.
+ setTimeout(() => Channel.fatalError("Server process crashed"), MsPerSecond * 10);
+ return;
+ }
- if (++gNumCrashes > MaxCrashes || gNoRecovery) {
- Channel.fatalError("Can't recover from crash: too many crashes");
- return;
- }
+ if (!LinkerProcess.shouldRespawnChildren()) {
+ return;
+ }
- const crashedProcessIds = [processId];
+ process.logger.error("RecoverFromCrash");
- // Mark any processes which were due to be forked as crashed as well.
- const forks = getTransitiveForks(processId);
- for (const id of forks) {
- process.logger.error("AlsoCrashed", { otherProcessId: id });
- crashedProcessIds.push(id);
- }
+ if (++gNumCrashes > MaxCrashes || gNoRecovery) {
+ Channel.fatalError("Can't recover from crash: too many crashes");
+ return;
+ }
- crashedProcessIds.sort((a, b) => (a > b ? 1 : -1));
+ const crashedProcessIds = [processId];
- const crashedProcesses: Process[] = [];
- crashedProcessIds.forEach(processId => {
- const process = gProcesses.get(processId);
- if (process) {
- process.terminate();
- crashedProcesses.push(process);
+ // Mark any processes which were due to be forked as crashed as well.
+ const forks = this.getTransitiveForks(processId);
+ for (const id of forks) {
+ process.logger.error("AlsoCrashed", { otherProcessId: id });
+ crashedProcessIds.push(id);
}
- });
- crashedProcesses.forEach(respawnCrashedProcess);
-}
+ crashedProcessIds.sort((a, b) => (a > b ? 1 : -1));
-export function getAllProcesses() {
- return [...gProcesses.values()];
+ const crashedProcesses: Process[] = [];
+ crashedProcessIds.forEach(processId => {
+ const process = this.processes.get(processId);
+ if (process) {
+ process.terminate();
+ crashedProcesses.push(process);
+ }
+ });
+
+ crashedProcesses.forEach(respawnCrashedProcess);
+ }
+
+ getAllProcesses() {
+ return [...this.processes.values()];
+ }
}
///////////////
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment