Created
January 28, 2021 23:24
-
-
Save jasonLaster/14b8fe54ad2f4f53df95131e1f8f8757 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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