@rehearsal-labs/retest 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -5
- package/dist/api/source-location.d.ts.map +1 -1
- package/dist/api/source-location.js +3 -1
- package/dist/browser/builds.d.ts +35 -6
- package/dist/browser/builds.d.ts.map +1 -1
- package/dist/browser/builds.js +115 -16
- package/dist/browser/cdp/transport.d.ts.map +1 -1
- package/dist/browser/cdp/transport.js +4 -4
- package/dist/browser/chromium-process.d.ts +23 -0
- package/dist/browser/chromium-process.d.ts.map +1 -1
- package/dist/browser/chromium-process.js +78 -13
- package/dist/browser/electron.d.ts +1 -1
- package/dist/browser/electron.d.ts.map +1 -1
- package/dist/browser/electron.js +6 -3
- package/dist/browser/executables.d.ts +16 -1
- package/dist/browser/executables.d.ts.map +1 -1
- package/dist/browser/executables.js +50 -18
- package/dist/browser/firefox/accessible-names.d.ts +5 -4
- package/dist/browser/firefox/accessible-names.d.ts.map +1 -1
- package/dist/browser/firefox/accessible-names.js +11 -6
- package/dist/browser/firefox/bridge.js +3 -2
- package/dist/browser/firefox/executable.d.ts +14 -14
- package/dist/browser/firefox/executable.d.ts.map +1 -1
- package/dist/browser/firefox/executable.js +29 -21
- package/dist/browser/firefox/launch.js +1 -1
- package/dist/browser/firefox/navigation.d.ts +5 -2
- package/dist/browser/firefox/navigation.d.ts.map +1 -1
- package/dist/browser/firefox/navigation.js +48 -14
- package/dist/browser/firefox/orphans.d.ts.map +1 -1
- package/dist/browser/firefox/orphans.js +34 -2
- package/dist/browser/firefox/page.d.ts.map +1 -1
- package/dist/browser/firefox/page.js +113 -19
- package/dist/browser/firefox/process.d.ts +20 -1
- package/dist/browser/firefox/process.d.ts.map +1 -1
- package/dist/browser/firefox/process.js +124 -22
- package/dist/browser/firefox/profile.d.ts +5 -0
- package/dist/browser/firefox/profile.d.ts.map +1 -1
- package/dist/browser/firefox/profile.js +17 -1
- package/dist/browser/firefox/storage.d.ts.map +1 -1
- package/dist/browser/firefox/storage.js +4 -2
- package/dist/browser/firefox/subscriptions.d.ts +26 -0
- package/dist/browser/firefox/subscriptions.d.ts.map +1 -0
- package/dist/browser/firefox/subscriptions.js +10 -0
- package/dist/browser/launch.d.ts +6 -0
- package/dist/browser/launch.d.ts.map +1 -1
- package/dist/browser/launch.js +14 -1
- package/dist/cli/commands/doctor.js +3 -3
- package/dist/cli/commands/inspect.js +3 -2
- package/dist/cli/commands/install.d.ts.map +1 -1
- package/dist/cli/commands/install.js +26 -13
- package/dist/cli/commands/licences.d.ts +22 -0
- package/dist/cli/commands/licences.d.ts.map +1 -1
- package/dist/cli/commands/licences.js +62 -20
- package/dist/cli/commands/run.js +2 -2
- package/dist/cli/doctor/checks.js +4 -1
- package/dist/cli/inspect/diagnostics.js +3 -3
- package/dist/cli/inspect/test-timeline.js +10 -10
- package/dist/cli/install/doctor-rows.d.ts.map +1 -1
- package/dist/cli/install/doctor-rows.js +5 -4
- package/dist/cli/install/file-changes.d.ts +44 -0
- package/dist/cli/install/file-changes.d.ts.map +1 -0
- package/dist/cli/install/file-changes.js +81 -0
- package/dist/cli/install/install-archive.d.ts +3 -1
- package/dist/cli/install/install-archive.d.ts.map +1 -1
- package/dist/cli/install/install-archive.js +80 -33
- package/dist/cli/install/lock.d.ts.map +1 -1
- package/dist/cli/install/lock.js +108 -21
- package/dist/cli/install/media-doctor.d.ts.map +1 -1
- package/dist/cli/install/media-doctor.js +2 -1
- package/dist/cli/install/media-install.d.ts.map +1 -1
- package/dist/cli/install/media-install.js +38 -19
- package/dist/cli/install/media-pins.d.ts +7 -1
- package/dist/cli/install/media-pins.d.ts.map +1 -1
- package/dist/cli/install/media-pins.js +23 -12
- package/dist/cli/install/media-record.d.ts.map +1 -1
- package/dist/cli/install/media-record.js +10 -9
- package/dist/cli/install/media-report.d.ts +3 -1
- package/dist/cli/install/media-report.d.ts.map +1 -1
- package/dist/cli/install/media-report.js +7 -5
- package/dist/cli/install/media-tools.d.ts.map +1 -1
- package/dist/cli/install/media-tools.js +6 -4
- package/dist/cli/install/process-start.d.ts +3 -2
- package/dist/cli/install/process-start.d.ts.map +1 -1
- package/dist/cli/install/process-start.js +4 -0
- package/dist/cli/install/report.d.ts.map +1 -1
- package/dist/cli/install/report.js +11 -7
- package/dist/cli/install/supervisor-install.d.ts +33 -0
- package/dist/cli/install/supervisor-install.d.ts.map +1 -0
- package/dist/cli/install/supervisor-install.js +158 -0
- package/dist/cli/install/supervisor-locate.d.ts +47 -0
- package/dist/cli/install/supervisor-locate.d.ts.map +1 -0
- package/dist/cli/install/supervisor-locate.js +113 -0
- package/dist/cli/install/supervisor-pins.d.ts +21 -0
- package/dist/cli/install/supervisor-pins.d.ts.map +1 -0
- package/dist/cli/install/supervisor-pins.js +28 -0
- package/dist/cli/install/supervisor-record.d.ts +31 -0
- package/dist/cli/install/supervisor-record.d.ts.map +1 -0
- package/dist/cli/install/supervisor-record.js +104 -0
- package/dist/cli/install/supervisor-report.d.ts +11 -0
- package/dist/cli/install/supervisor-report.d.ts.map +1 -0
- package/dist/cli/install/supervisor-report.js +33 -0
- package/dist/cli/install/supervisor-tools.d.ts +43 -0
- package/dist/cli/install/supervisor-tools.d.ts.map +1 -0
- package/dist/cli/install/supervisor-tools.js +114 -0
- package/dist/cli/install/unpack.d.ts +23 -3
- package/dist/cli/install/unpack.d.ts.map +1 -1
- package/dist/cli/install/unpack.js +124 -10
- package/dist/cli/install/zip-member.d.ts +15 -0
- package/dist/cli/install/zip-member.d.ts.map +1 -0
- package/dist/cli/install/zip-member.js +77 -0
- package/dist/cli/interrupt.d.ts +1 -1
- package/dist/cli/interrupt.d.ts.map +1 -1
- package/dist/cli/interrupt.js +15 -10
- package/dist/cli/terminal.d.ts +9 -1
- package/dist/cli/terminal.d.ts.map +1 -1
- package/dist/cli/terminal.js +14 -0
- package/dist/config/define.d.ts +2 -2
- package/dist/config/define.js +2 -2
- package/dist/diagnostics/firefox-collector.d.ts +11 -10
- package/dist/diagnostics/firefox-collector.d.ts.map +1 -1
- package/dist/diagnostics/firefox-collector.js +16 -11
- package/dist/media/client.d.ts +2 -1
- package/dist/media/client.d.ts.map +1 -1
- package/dist/media/client.js +16 -5
- package/dist/media/host.d.ts +32 -0
- package/dist/media/host.d.ts.map +1 -0
- package/dist/media/host.js +50 -0
- package/dist/media/locate.d.ts.map +1 -1
- package/dist/media/locate.js +4 -3
- package/dist/native/processes.d.ts.map +1 -1
- package/dist/native/processes.js +7 -3
- package/dist/protocol/files.d.ts +1 -1
- package/dist/protocol/files.d.ts.map +1 -1
- package/dist/protocol/files.js +10 -5
- package/dist/reporters/commands.d.ts +12 -3
- package/dist/reporters/commands.d.ts.map +1 -1
- package/dist/reporters/commands.js +29 -11
- package/dist/reporters/human-card.js +1 -1
- package/dist/reporters/human.d.ts +3 -1
- package/dist/reporters/human.d.ts.map +1 -1
- package/dist/reporters/human.js +8 -8
- package/dist/reporters/style.d.ts +21 -2
- package/dist/reporters/style.d.ts.map +1 -1
- package/dist/reporters/style.js +11 -2
- package/dist/runner/app-server.d.ts +27 -7
- package/dist/runner/app-server.d.ts.map +1 -1
- package/dist/runner/app-server.js +74 -24
- package/dist/runner/child.js +6 -2
- package/dist/runner/media-leftovers.d.ts +7 -3
- package/dist/runner/media-leftovers.d.ts.map +1 -1
- package/dist/runner/media-leftovers.js +27 -6
- package/dist/runner/resources.d.ts +8 -0
- package/dist/runner/resources.d.ts.map +1 -1
- package/dist/runner/resources.js +12 -1
- package/dist/runner/run-session.d.ts.map +1 -1
- package/dist/runner/run-session.js +9 -4
- package/dist/runner/run.d.ts.map +1 -1
- package/dist/runner/run.js +2 -1
- package/dist/runner/target-drivers.d.ts +5 -2
- package/dist/runner/target-drivers.d.ts.map +1 -1
- package/dist/runner/target-drivers.js +10 -1
- package/dist/runner/test-file-process.d.ts +8 -0
- package/dist/runner/test-file-process.d.ts.map +1 -1
- package/dist/runner/test-file-process.js +26 -3
- package/dist/runner/test-pages.d.ts.map +1 -1
- package/dist/runner/test-pages.js +5 -2
- package/dist/shared/environment.d.ts +17 -0
- package/dist/shared/environment.d.ts.map +1 -0
- package/dist/shared/environment.js +27 -0
- package/dist/shared/metadata-process-worker.js +15 -7
- package/dist/shared/metadata-process.d.ts +5 -0
- package/dist/shared/metadata-process.d.ts.map +1 -1
- package/dist/shared/metadata-process.js +36 -6
- package/dist/shared/posix-path.d.ts +12 -0
- package/dist/shared/posix-path.d.ts.map +1 -1
- package/dist/shared/posix-path.js +16 -0
- package/dist/shared/private-file.d.ts +38 -0
- package/dist/shared/private-file.d.ts.map +1 -0
- package/dist/shared/private-file.js +132 -0
- package/dist/shared/process-ownership.d.ts +52 -2
- package/dist/shared/process-ownership.d.ts.map +1 -1
- package/dist/shared/process-ownership.js +104 -11
- package/dist/shared/process-supervisor.d.ts +309 -0
- package/dist/shared/process-supervisor.d.ts.map +1 -0
- package/dist/shared/process-supervisor.js +737 -0
- package/dist/shared/process-system.d.ts +113 -0
- package/dist/shared/process-system.d.ts.map +1 -0
- package/dist/shared/process-system.js +254 -0
- package/dist/shared/regular-file.d.ts +2 -2
- package/dist/shared/regular-file.d.ts.map +1 -1
- package/dist/shared/regular-file.js +19 -2
- package/dist/store/artifacts.d.ts +5 -4
- package/dist/store/artifacts.d.ts.map +1 -1
- package/dist/store/artifacts.js +18 -5
- package/dist/store/run-store.d.ts +5 -2
- package/dist/store/run-store.d.ts.map +1 -1
- package/dist/store/run-store.js +48 -4
- package/media/Cargo.lock +16 -0
- package/media/Cargo.toml +16 -1
- package/media/src/encoder.rs +56 -12
- package/media/src/frame.rs +7 -1
- package/media/src/main.rs +20 -2
- package/media/src/place.rs +230 -11
- package/media/src/process_ownership_windows.rs +1058 -0
- package/media/src/recording.rs +15 -7
- package/media/src/replies.rs +55 -0
- package/media/src/server.rs +72 -2
- package/media/src/store.rs +71 -2
- package/package.json +9 -4
- package/src/cli/install/media-notices.txt +465 -1
- package/supervisor/Cargo.lock +25 -0
- package/supervisor/Cargo.toml +22 -0
- package/supervisor/NOTICES +464 -0
- package/supervisor/build.rs +44 -0
- package/supervisor/src/command.rs +612 -0
- package/supervisor/src/jobs.rs +1650 -0
- package/supervisor/src/main.rs +71 -0
- package/supervisor/src/reply.rs +367 -0
|
@@ -21,26 +21,76 @@ export type ProcessOwnershipSystem = {
|
|
|
21
21
|
readAsync?(deadline?: Deadline): Promise<readonly OwnedProcessIdentity[]>;
|
|
22
22
|
/** The same immediate pre-signal reading without holding the event loop. */
|
|
23
23
|
readProcessAsync?(pid: number, deadline?: Deadline): Promise<OwnedProcessIdentity | undefined>;
|
|
24
|
-
signal
|
|
24
|
+
/** `expected` is the fresh reading the signal follows, for a host that checks it again as it signals. */
|
|
25
|
+
signal(pid: number, signal: NodeJS.Signals | 0, expected?: OwnedProcessIdentity): void;
|
|
26
|
+
/**
|
|
27
|
+
* Set where `read` lists one job's processes and nothing else, as on Windows: the job the launch `root` was put in,
|
|
28
|
+
* which holds every process it and its descendants started. There, a member is owned by being in the job, and the
|
|
29
|
+
* group is ended by ending the job.
|
|
30
|
+
*/
|
|
31
|
+
job?: OwnedJob;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* A launch's job: the pid it was made for, and its end, which ends every process in it at once. A job holds only
|
|
35
|
+
* processes born of the launch, so ending it ends nothing else, and nothing in it is left out.
|
|
36
|
+
*/
|
|
37
|
+
export type OwnedJob = {
|
|
38
|
+
readonly root: number;
|
|
39
|
+
/**
|
|
40
|
+
* The launch as it was read when it was put in the job, alive. A process gone from the job is gone from its list at
|
|
41
|
+
* once, where Unix still shows it until it is reaped, so a launch that ended before the first reading is recorded
|
|
42
|
+
* from this.
|
|
43
|
+
*/
|
|
44
|
+
readonly launched?: OwnedProcessIdentity;
|
|
45
|
+
end(deadline?: Deadline): void;
|
|
46
|
+
endAsync(deadline?: Deadline): Promise<void>;
|
|
47
|
+
/** Sends Ctrl+C to the console the job's processes are on, which is how a console program is asked to stop. */
|
|
48
|
+
interrupt(deadline?: Deadline): void;
|
|
49
|
+
/** What the job's end could not confirm, once the job was read empty: processes still running outside every job. */
|
|
50
|
+
unconfirmed(): readonly string[];
|
|
25
51
|
};
|
|
26
52
|
/** Signal failures stay failures; identity refusals can be reconciled only by a later proof of absence. */
|
|
27
53
|
export type ProcessSignalReport = {
|
|
28
54
|
readonly problems: readonly string[];
|
|
29
55
|
readonly identityRefusals: readonly string[];
|
|
30
56
|
};
|
|
57
|
+
/** What one reading of whether a group remains said: the processes of the group it found running, or why it failed. */
|
|
58
|
+
export type LivenessReading = {
|
|
59
|
+
readonly running: readonly OwnedProcessIdentity[];
|
|
60
|
+
} | {
|
|
61
|
+
readonly problem: string;
|
|
62
|
+
};
|
|
31
63
|
/**
|
|
32
64
|
* Records a launched process and the descendants observed beneath a still-verified owned process. Group membership
|
|
33
65
|
* alone never establishes ownership. Signals are sent to recorded, freshly verified pids, never to a numeric group.
|
|
66
|
+
* A launch held in a job of its own, as on Windows, is the exception the job makes possible: the job holds nothing but
|
|
67
|
+
* what the launch started, so its members are owned by being there, and it is ended whole.
|
|
34
68
|
*/
|
|
35
69
|
export declare class OwnedProcessGroup {
|
|
36
70
|
#private;
|
|
37
71
|
constructor(pid: number, parentPid?: number, system?: ProcessOwnershipSystem);
|
|
38
72
|
/** The first successful host reading found no launched pid. A failed reading never sets this fact. */
|
|
39
73
|
get initialProcessAbsent(): boolean;
|
|
40
|
-
/**
|
|
74
|
+
/**
|
|
75
|
+
* Failed metadata readings remain visible even when a later reading proves the launch ended, as does, for a launch
|
|
76
|
+
* held in a job, anything its job's end could not confirm.
|
|
77
|
+
*/
|
|
41
78
|
get readProblems(): readonly string[];
|
|
42
79
|
/** Whether the launch has been read once, whatever the reading found or however it failed. */
|
|
43
80
|
get captured(): boolean;
|
|
81
|
+
/** Whether this group is a launch held in a job of its own, which ends it whole rather than one signal at a time. */
|
|
82
|
+
get heldByJob(): boolean;
|
|
83
|
+
/**
|
|
84
|
+
* The processes of the group on record, recorded or not traced to the launch, as the newest reading that succeeded
|
|
85
|
+
* left them. A reading that failed changes nothing here, so this is no proof that they still run. Empty once a reading
|
|
86
|
+
* found the group gone.
|
|
87
|
+
*/
|
|
88
|
+
get stillThere(): readonly OwnedProcessIdentity[];
|
|
89
|
+
/**
|
|
90
|
+
* What the newest reading of whether the group remains said: the processes of the group it found still running, or
|
|
91
|
+
* the problem it failed with. Undefined before the first.
|
|
92
|
+
*/
|
|
93
|
+
get lastLook(): LivenessReading | undefined;
|
|
44
94
|
/** Records descendants only while their chain reaches an already verified process this owner launched. */
|
|
45
95
|
capture(deadline?: Deadline): string[];
|
|
46
96
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process-ownership.d.ts","sourceRoot":"","sources":["../../src/shared/process-ownership.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAKvD,sEAAsE;AACtE,MAAM,MAAM,oBAAoB,GAAG;IACjC,GAAG,EAAE,MAAM,CAAA;IACX,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,8FAA8F;IAC9F,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AAED,MAAM,MAAM,sBAAsB,GAAG;IACnC,IAAI,CAAC,QAAQ,CAAC,EAAE,QAAQ,GAAG,SAAS,oBAAoB,EAAE,CAAA;IAC1D;;;;OAIG;IACH,WAAW,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,QAAQ,GAAG,oBAAoB,GAAG,SAAS,CAAA;IAChF,uHAAuH;IACvH,SAAS,CAAC,CAAC,QAAQ,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,SAAS,oBAAoB,EAAE,CAAC,CAAA;IACzE,4EAA4E;IAC5E,gBAAgB,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,oBAAoB,GAAG,SAAS,CAAC,CAAA;IAC9F,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,CAAC,GAAG,IAAI,CAAA;
|
|
1
|
+
{"version":3,"file":"process-ownership.d.ts","sourceRoot":"","sources":["../../src/shared/process-ownership.ts"],"names":[],"mappings":"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"}
|
|
@@ -11,6 +11,8 @@ const host = {
|
|
|
11
11
|
/**
|
|
12
12
|
* Records a launched process and the descendants observed beneath a still-verified owned process. Group membership
|
|
13
13
|
* alone never establishes ownership. Signals are sent to recorded, freshly verified pids, never to a numeric group.
|
|
14
|
+
* A launch held in a job of its own, as on Windows, is the exception the job makes possible: the job holds nothing but
|
|
15
|
+
* what the launch started, so its members are owned by being there, and it is ended whole.
|
|
14
16
|
*/
|
|
15
17
|
export class OwnedProcessGroup {
|
|
16
18
|
#pid;
|
|
@@ -19,6 +21,7 @@ export class OwnedProcessGroup {
|
|
|
19
21
|
#records = new Map();
|
|
20
22
|
#unowned = new Map();
|
|
21
23
|
#readProblems = new Set();
|
|
24
|
+
#lastLook;
|
|
22
25
|
#initialized = false;
|
|
23
26
|
#retired = false;
|
|
24
27
|
#initialProcessAbsent = false;
|
|
@@ -43,14 +46,41 @@ export class OwnedProcessGroup {
|
|
|
43
46
|
get initialProcessAbsent() {
|
|
44
47
|
return this.#initialProcessAbsent;
|
|
45
48
|
}
|
|
46
|
-
/**
|
|
49
|
+
/**
|
|
50
|
+
* Failed metadata readings remain visible even when a later reading proves the launch ended, as does, for a launch
|
|
51
|
+
* held in a job, anything its job's end could not confirm.
|
|
52
|
+
*/
|
|
47
53
|
get readProblems() {
|
|
48
|
-
return [...this.#readProblems];
|
|
54
|
+
return [...this.#readProblems, ...(this.#ownJob()?.unconfirmed() ?? [])];
|
|
49
55
|
}
|
|
50
56
|
/** Whether the launch has been read once, whatever the reading found or however it failed. */
|
|
51
57
|
get captured() {
|
|
52
58
|
return this.#initialized;
|
|
53
59
|
}
|
|
60
|
+
/** Whether this group is a launch held in a job of its own, which ends it whole rather than one signal at a time. */
|
|
61
|
+
get heldByJob() {
|
|
62
|
+
return this.#ownJob() !== undefined;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* The processes of the group on record, recorded or not traced to the launch, as the newest reading that succeeded
|
|
66
|
+
* left them. A reading that failed changes nothing here, so this is no proof that they still run. Empty once a reading
|
|
67
|
+
* found the group gone.
|
|
68
|
+
*/
|
|
69
|
+
get stillThere() {
|
|
70
|
+
return [...this.#records.values(), ...this.#unowned.values()];
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* What the newest reading of whether the group remains said: the processes of the group it found still running, or
|
|
74
|
+
* the problem it failed with. Undefined before the first.
|
|
75
|
+
*/
|
|
76
|
+
get lastLook() {
|
|
77
|
+
return this.#lastLook;
|
|
78
|
+
}
|
|
79
|
+
// The job of this very launch; a descendant handed off by `groupFor` shares the system but is not its job's root.
|
|
80
|
+
#ownJob() {
|
|
81
|
+
const { job } = this.#system;
|
|
82
|
+
return job?.root === this.#pid ? job : undefined;
|
|
83
|
+
}
|
|
54
84
|
#failedRead(error) {
|
|
55
85
|
const problem = `Could not read ownership of process ${this.#pid}: ${errorMessage(error)}`;
|
|
56
86
|
this.#readProblems.add(problem);
|
|
@@ -104,7 +134,7 @@ export class OwnedProcessGroup {
|
|
|
104
134
|
this.#newest = Math.max(this.#newest, sequence);
|
|
105
135
|
const initial = !this.#initialized;
|
|
106
136
|
this.#initialized = true;
|
|
107
|
-
const root = processes.find((entry) => entry.pid === this.#pid);
|
|
137
|
+
const root = processes.find((entry) => entry.pid === this.#pid) ?? (initial ? this.#ownJob()?.launched : undefined);
|
|
108
138
|
if (initial) {
|
|
109
139
|
if (root === undefined) {
|
|
110
140
|
this.#initialProcessAbsent = true;
|
|
@@ -115,6 +145,12 @@ export class OwnedProcessGroup {
|
|
|
115
145
|
this.#records.set(root.pid, root);
|
|
116
146
|
this.#launchIdentity = root;
|
|
117
147
|
}
|
|
148
|
+
// A job lists only processes born of its launch, even one whose parent is gone, so its members need no ancestry.
|
|
149
|
+
if (this.#ownJob() !== undefined) {
|
|
150
|
+
for (const entry of processes)
|
|
151
|
+
if (running(entry) && entry.groupId === this.#pid && !this.#records.has(entry.pid))
|
|
152
|
+
this.#records.set(entry.pid, entry);
|
|
153
|
+
}
|
|
118
154
|
for (const entry of processes) {
|
|
119
155
|
const record = this.#records.get(entry.pid);
|
|
120
156
|
// A process recorded while its command could not be read keeps the first readable one, so a later change is seen.
|
|
@@ -217,6 +253,11 @@ export class OwnedProcessGroup {
|
|
|
217
253
|
signalReport(signal, deadline) {
|
|
218
254
|
if (this.#retired)
|
|
219
255
|
return { problems: [], identityRefusals: [] };
|
|
256
|
+
const job = this.#ownJob();
|
|
257
|
+
if (job !== undefined && endsProcess(signal))
|
|
258
|
+
return this.#endJob(job, deadline);
|
|
259
|
+
if (job !== undefined && signal === 'SIGINT')
|
|
260
|
+
return this.#interruptJob(job, deadline);
|
|
220
261
|
let processes;
|
|
221
262
|
try {
|
|
222
263
|
checkDeadline(deadline);
|
|
@@ -252,6 +293,11 @@ export class OwnedProcessGroup {
|
|
|
252
293
|
async signalReportAsync(signal, deadline) {
|
|
253
294
|
if (this.#retired)
|
|
254
295
|
return { problems: [], identityRefusals: [] };
|
|
296
|
+
const job = this.#ownJob();
|
|
297
|
+
if (job !== undefined && endsProcess(signal))
|
|
298
|
+
return this.#endJobAsync(job, deadline);
|
|
299
|
+
if (job !== undefined && signal === 'SIGINT')
|
|
300
|
+
return this.#interruptJob(job, deadline);
|
|
255
301
|
const asked = this.#sequence;
|
|
256
302
|
let read;
|
|
257
303
|
try {
|
|
@@ -285,6 +331,41 @@ export class OwnedProcessGroup {
|
|
|
285
331
|
}
|
|
286
332
|
return { problems, identityRefusals };
|
|
287
333
|
}
|
|
334
|
+
// Windows has no SIGINT to send; a console program is asked to stop by Ctrl+C on its console, which reaches every
|
|
335
|
+
// process on it at once, so it is sent once for the launch. It is only asked: one that cannot be asked, as one with no
|
|
336
|
+
// console left, is ended when its grace runs out, as one that ignores Ctrl+C is, and that end is what cleanup reports.
|
|
337
|
+
#interruptJob(job, deadline) {
|
|
338
|
+
try {
|
|
339
|
+
checkDeadline(deadline);
|
|
340
|
+
job.interrupt(deadline);
|
|
341
|
+
}
|
|
342
|
+
catch {
|
|
343
|
+
// As above: the end that follows is the outcome.
|
|
344
|
+
}
|
|
345
|
+
return { problems: [], identityRefusals: [] };
|
|
346
|
+
}
|
|
347
|
+
// A job is ended whole, without a reading first: it holds only what the launch started, so nothing else can be in it,
|
|
348
|
+
// and a helper born a moment ago is in it too. Whether it is then gone is for `remains` to read.
|
|
349
|
+
#endJob(job, deadline) {
|
|
350
|
+
try {
|
|
351
|
+
checkDeadline(deadline);
|
|
352
|
+
job.end(deadline);
|
|
353
|
+
}
|
|
354
|
+
catch (error) {
|
|
355
|
+
return { problems: [endProblem(this.#pid, error)], identityRefusals: [] };
|
|
356
|
+
}
|
|
357
|
+
return { problems: [], identityRefusals: [] };
|
|
358
|
+
}
|
|
359
|
+
async #endJobAsync(job, deadline) {
|
|
360
|
+
try {
|
|
361
|
+
checkDeadline(deadline);
|
|
362
|
+
await job.endAsync(deadline);
|
|
363
|
+
}
|
|
364
|
+
catch (error) {
|
|
365
|
+
return { problems: [endProblem(this.#pid, error)], identityRefusals: [] };
|
|
366
|
+
}
|
|
367
|
+
return { problems: [], identityRefusals: [] };
|
|
368
|
+
}
|
|
288
369
|
#signalCurrent(record, current, signal, problems, identityRefusals, deadline) {
|
|
289
370
|
// Another awaited cleanup may already have confirmed this record gone. It must not be restored by a late reply.
|
|
290
371
|
if (this.#retired || !sameProcess(this.#records.get(record.pid), record))
|
|
@@ -310,7 +391,7 @@ export class OwnedProcessGroup {
|
|
|
310
391
|
}
|
|
311
392
|
try {
|
|
312
393
|
checkDeadline(deadline);
|
|
313
|
-
this.#system.signal(record.pid, signal);
|
|
394
|
+
this.#system.signal(record.pid, signal, current);
|
|
314
395
|
}
|
|
315
396
|
catch (error) {
|
|
316
397
|
if (errorCode(error) !== 'ESRCH')
|
|
@@ -411,7 +492,7 @@ export class OwnedProcessGroup {
|
|
|
411
492
|
checkDeadline(deadline);
|
|
412
493
|
}
|
|
413
494
|
catch (error) {
|
|
414
|
-
this.#failedRead(error);
|
|
495
|
+
this.#lastLook = { problem: this.#failedRead(error) };
|
|
415
496
|
return true;
|
|
416
497
|
}
|
|
417
498
|
return this.#remainsFrom(processes, this.#next());
|
|
@@ -432,7 +513,7 @@ export class OwnedProcessGroup {
|
|
|
432
513
|
checkDeadline(deadline);
|
|
433
514
|
}
|
|
434
515
|
catch (error) {
|
|
435
|
-
this.#failedRead(error);
|
|
516
|
+
this.#lastLook = { problem: this.#failedRead(error) };
|
|
436
517
|
return true;
|
|
437
518
|
}
|
|
438
519
|
if (this.#retired || read === undefined)
|
|
@@ -443,8 +524,12 @@ export class OwnedProcessGroup {
|
|
|
443
524
|
this.#newest = Math.max(this.#newest, sequence);
|
|
444
525
|
// A failed first reading never grants signal authority, and an empty ledger is no proof that the launched
|
|
445
526
|
// child ended. Until its pid and group are absent, that unresolved launch continues to hold its resource.
|
|
446
|
-
if (this.#launchIdentity === undefined
|
|
447
|
-
|
|
527
|
+
if (this.#launchIdentity === undefined) {
|
|
528
|
+
const unresolved = processes.filter((entry) => running(entry) && (entry.pid === this.#pid || entry.groupId === this.#pid));
|
|
529
|
+
this.#lastLook = { running: unresolved };
|
|
530
|
+
if (unresolved.length > 0)
|
|
531
|
+
return true;
|
|
532
|
+
}
|
|
448
533
|
const root = processes.find((entry) => entry.pid === this.#pid);
|
|
449
534
|
const reusedGroup = root !== undefined && this.#launchIdentity !== undefined && !sameBirth(this.#launchIdentity, root);
|
|
450
535
|
if (!reusedGroup)
|
|
@@ -453,9 +538,10 @@ export class OwnedProcessGroup {
|
|
|
453
538
|
this.#unowned.set(current.pid, current);
|
|
454
539
|
}
|
|
455
540
|
this.#forgetGone(processes);
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
541
|
+
const left = processes.filter((current) => running(current) && (sameBirth(this.#records.get(current.pid), current) || sameBirth(this.#unowned.get(current.pid), current)));
|
|
542
|
+
this.#lastLook = { running: left };
|
|
543
|
+
if (left.length > 0)
|
|
544
|
+
return true;
|
|
459
545
|
this.#retired = true;
|
|
460
546
|
this.#records.clear();
|
|
461
547
|
this.#unowned.clear();
|
|
@@ -471,6 +557,13 @@ export class OwnedProcessGroup {
|
|
|
471
557
|
export function unverifiedMembersProblem(groupId) {
|
|
472
558
|
return `Process group ${groupId} contains processes whose launch ownership could not be verified; they were left alone.`;
|
|
473
559
|
}
|
|
560
|
+
// The signals a job's end stands for. Windows has no gentler end than its job's, so SIGTERM ends a job as SIGKILL does.
|
|
561
|
+
function endsProcess(signal) {
|
|
562
|
+
return signal === 'SIGKILL' || signal === 'SIGTERM';
|
|
563
|
+
}
|
|
564
|
+
function endProblem(pid, error) {
|
|
565
|
+
return `Could not end the job holding process ${pid} and what it started: ${errorMessage(error)}`;
|
|
566
|
+
}
|
|
474
567
|
function sameProcess(record, current) {
|
|
475
568
|
return record !== undefined && sameProcessIdentity(record, current);
|
|
476
569
|
}
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
import type { OwnedJob, ProcessOwnershipSystem } from './process-ownership.ts';
|
|
2
|
+
import type { Deadline } from '../protocol/deadline.ts';
|
|
3
|
+
/** How to run the supervisor: its executable, the arguments before each command, and its whole environment. */
|
|
4
|
+
export type SupervisorProgram = {
|
|
5
|
+
readonly command: string;
|
|
6
|
+
readonly args: readonly string[];
|
|
7
|
+
readonly environment: Readonly<Record<string, string>>;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* One process as the supervisor read it, every field from one handle on it. `startedAt` is the 100 ns ticks since 1601
|
|
11
|
+
* Windows keeps, as digits; `commandLine` what it was started with.
|
|
12
|
+
*/
|
|
13
|
+
export type SupervisedProcess = {
|
|
14
|
+
readonly pid: number;
|
|
15
|
+
readonly parentPid: number | undefined;
|
|
16
|
+
readonly startedAt: string;
|
|
17
|
+
readonly image: string | undefined;
|
|
18
|
+
readonly commandLine: string | undefined;
|
|
19
|
+
};
|
|
20
|
+
/** The runner's own job: its name, and the value of the runner's handle that keeps it. */
|
|
21
|
+
export type HeldRunner = {
|
|
22
|
+
readonly job: string;
|
|
23
|
+
readonly handle: number;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* A launch held in a job of its own: the job, the runner's handle to it, the launched process, whether it had already
|
|
27
|
+
* ended, so only what it started is in the job, the processes it had already started before it was held, which the
|
|
28
|
+
* supervisor held then, those it found already in a job of their own inside the runner's, which the process that
|
|
29
|
+
* started them holds, any it could not hold, and whether the search for them finished.
|
|
30
|
+
*/
|
|
31
|
+
export type HeldLaunch = {
|
|
32
|
+
readonly job: string;
|
|
33
|
+
readonly handle: number;
|
|
34
|
+
readonly root: SupervisedProcess;
|
|
35
|
+
readonly ended: boolean;
|
|
36
|
+
readonly late: readonly SupervisedProcess[];
|
|
37
|
+
readonly byParent: readonly SupervisedProcess[];
|
|
38
|
+
readonly unheld: readonly number[];
|
|
39
|
+
readonly complete: boolean;
|
|
40
|
+
};
|
|
41
|
+
/** The console Ctrl+C went to, by the job's process it was reached through, and every process on that console. */
|
|
42
|
+
export type Interrupted = {
|
|
43
|
+
readonly console: number;
|
|
44
|
+
readonly reached: readonly number[];
|
|
45
|
+
};
|
|
46
|
+
/** What `terminate` found under the pid: the recorded process, ended; nothing; or another process. */
|
|
47
|
+
export type TerminateOutcome = 'terminated' | 'absent' | 'different';
|
|
48
|
+
/** One process in a reply, as the supervisor prints it. */
|
|
49
|
+
type Identity = {
|
|
50
|
+
pid: number;
|
|
51
|
+
parentPid: number | null;
|
|
52
|
+
startedAt: string;
|
|
53
|
+
image: string | null;
|
|
54
|
+
commandLine: string | null;
|
|
55
|
+
};
|
|
56
|
+
/** The one line the supervisor prints for each command, a refusal included. */
|
|
57
|
+
export type SupervisorReply = {
|
|
58
|
+
schemaVersion: 1;
|
|
59
|
+
type: 'held';
|
|
60
|
+
job: string;
|
|
61
|
+
runner: number;
|
|
62
|
+
handle: number;
|
|
63
|
+
} | {
|
|
64
|
+
schemaVersion: 1;
|
|
65
|
+
type: 'adopted';
|
|
66
|
+
job: string;
|
|
67
|
+
handle: number;
|
|
68
|
+
root: Identity;
|
|
69
|
+
ended: boolean;
|
|
70
|
+
late: Identity[];
|
|
71
|
+
byParent: Identity[];
|
|
72
|
+
unheld: number[];
|
|
73
|
+
complete: boolean;
|
|
74
|
+
} | {
|
|
75
|
+
schemaVersion: 1;
|
|
76
|
+
type: 'members';
|
|
77
|
+
job: string;
|
|
78
|
+
processes: Identity[];
|
|
79
|
+
} | {
|
|
80
|
+
schemaVersion: 1;
|
|
81
|
+
type: 'process';
|
|
82
|
+
process: Identity | null;
|
|
83
|
+
inJob: boolean | null;
|
|
84
|
+
} | {
|
|
85
|
+
schemaVersion: 1;
|
|
86
|
+
type: 'ended';
|
|
87
|
+
job: string;
|
|
88
|
+
} | {
|
|
89
|
+
schemaVersion: 1;
|
|
90
|
+
type: 'terminated';
|
|
91
|
+
pid: number;
|
|
92
|
+
outcome: TerminateOutcome;
|
|
93
|
+
} | {
|
|
94
|
+
schemaVersion: 1;
|
|
95
|
+
type: 'released';
|
|
96
|
+
job: string;
|
|
97
|
+
} | {
|
|
98
|
+
schemaVersion: 1;
|
|
99
|
+
type: 'strays';
|
|
100
|
+
job: string;
|
|
101
|
+
processes: Identity[];
|
|
102
|
+
} | {
|
|
103
|
+
schemaVersion: 1;
|
|
104
|
+
type: 'interrupted';
|
|
105
|
+
job: string;
|
|
106
|
+
console: number;
|
|
107
|
+
reached: number[];
|
|
108
|
+
} | {
|
|
109
|
+
schemaVersion: 1;
|
|
110
|
+
type: 'refused';
|
|
111
|
+
problem: string;
|
|
112
|
+
detail: string | null;
|
|
113
|
+
};
|
|
114
|
+
type Reply = SupervisorReply;
|
|
115
|
+
/**
|
|
116
|
+
* The supervisor's answers for one runner, the process that asks. Every job it makes is named after the runner and a
|
|
117
|
+
* random word chosen here, so the names are new and nobody else's; a name already taken is refused by the supervisor.
|
|
118
|
+
* A launch's job also carries the launch's pid and a count, so a later launch given the same pid gets a name of its
|
|
119
|
+
* own. Each method runs the supervisor once; a refusal throws with the supervisor's own sentence, and the Windows call
|
|
120
|
+
* behind it, when one failed, as the error's cause.
|
|
121
|
+
*
|
|
122
|
+
* @example const supervisor = new Supervisor(program); supervisor.hold(); const launch = supervisor.adopt(child.pid)
|
|
123
|
+
*/
|
|
124
|
+
export declare class Supervisor {
|
|
125
|
+
#private;
|
|
126
|
+
readonly program: SupervisorProgram;
|
|
127
|
+
readonly runner: number;
|
|
128
|
+
constructor(program: SupervisorProgram, runner?: number, word?: string);
|
|
129
|
+
/** The name of the runner's own job. */
|
|
130
|
+
get runnerJob(): string;
|
|
131
|
+
/** The name the next launch with this pid is held under. */
|
|
132
|
+
launchJob(pid: number): string;
|
|
133
|
+
/** The jobs of launches the runner holds a handle to, oldest first. */
|
|
134
|
+
get launchJobs(): readonly string[];
|
|
135
|
+
/**
|
|
136
|
+
* The launches the runner holds a handle to, each by its job, the process it was made for, what that held by its
|
|
137
|
+
* parent when it was held, and the markers it was held with.
|
|
138
|
+
*/
|
|
139
|
+
get launches(): readonly {
|
|
140
|
+
readonly job: string;
|
|
141
|
+
readonly root: SupervisedProcess;
|
|
142
|
+
readonly byParent: readonly SupervisedProcess[];
|
|
143
|
+
readonly markers: readonly string[];
|
|
144
|
+
}[];
|
|
145
|
+
/** The processes named so far, by pid and start, as they stand now: what a later `forgetEnded` may forget. */
|
|
146
|
+
get named(): ReadonlySet<string>;
|
|
147
|
+
/**
|
|
148
|
+
* Forgets those of `named`, taken before `runnerJob` was read, that this reading of the runner's job no longer holds:
|
|
149
|
+
* each has ended, and a process given its pid later is another one. A process named after `named` was taken is kept,
|
|
150
|
+
* whatever the reading says, since the reading may be older than its naming.
|
|
151
|
+
*/
|
|
152
|
+
forgetEnded(named: ReadonlySet<string>, runnerJob: readonly SupervisedProcess[]): void;
|
|
153
|
+
/** How many processes are named now, which `forgetEnded` keeps to those still running. */
|
|
154
|
+
get namedCount(): number;
|
|
155
|
+
/**
|
|
156
|
+
* Of these processes, those not named before, each counted as named from now on. One no handle could read, whose
|
|
157
|
+
* start is 0, is named by its pid alone, and a later reading of the same pid is that process, named already.
|
|
158
|
+
*/
|
|
159
|
+
firstNamed(processes: readonly SupervisedProcess[]): readonly SupervisedProcess[];
|
|
160
|
+
/** Puts the runner in its own job, which ends everything in it once the runner ends. */
|
|
161
|
+
hold(deadline?: Deadline): HeldRunner;
|
|
162
|
+
/**
|
|
163
|
+
* Puts a child the runner just started in a job of its own, with whatever it already started. When no answer says it
|
|
164
|
+
* was held, whatever the job came to hold is ended: a reply lost after the job was made leaves only an empty job,
|
|
165
|
+
* whose handle goes with the runner.
|
|
166
|
+
*/
|
|
167
|
+
adopt(pid: number, deadline?: Deadline, markers?: readonly string[]): HeldLaunch;
|
|
168
|
+
/** The processes a job holds now. */
|
|
169
|
+
members(job: string, deadline?: Deadline): readonly SupervisedProcess[];
|
|
170
|
+
membersAsync(job: string, deadline?: Deadline): Promise<readonly SupervisedProcess[]>;
|
|
171
|
+
/** One process as it is now, or undefined when no process runs under the pid, and whether the job, if named, holds it. */
|
|
172
|
+
process(pid: number, job?: string, deadline?: Deadline): {
|
|
173
|
+
readonly process: SupervisedProcess | undefined;
|
|
174
|
+
readonly inJob: boolean;
|
|
175
|
+
};
|
|
176
|
+
processAsync(pid: number, job?: string, deadline?: Deadline): Promise<{
|
|
177
|
+
readonly process: SupervisedProcess | undefined;
|
|
178
|
+
readonly inJob: boolean;
|
|
179
|
+
}>;
|
|
180
|
+
/** Ends every process a launch's job holds. The supervisor refuses a job that holds the runner. */
|
|
181
|
+
end(job: string, deadline?: Deadline): void;
|
|
182
|
+
endAsync(job: string, deadline?: Deadline): Promise<void>;
|
|
183
|
+
/** Ends one process of a job only while it is the process that started at `startedAt`. */
|
|
184
|
+
terminate(job: string, pid: number, startedAt: string, deadline?: Deadline): TerminateOutcome;
|
|
185
|
+
terminateAsync(job: string, pid: number, startedAt: string, deadline?: Deadline): Promise<TerminateOutcome>;
|
|
186
|
+
/**
|
|
187
|
+
* The pids every launch but `job`'s holds now, in its job or, as it was held, by its parent, for a claim that rests on
|
|
188
|
+
* a marker or on a browser read one reading late, which must never take another launch's process; undefined when a
|
|
189
|
+
* job still held could not be read.
|
|
190
|
+
*/
|
|
191
|
+
otherLaunchMembers(job: string, deadline?: Deadline): ReadonlySet<number> | undefined;
|
|
192
|
+
otherLaunchMembersAsync(job: string, deadline?: Deadline): Promise<ReadonlySet<number> | undefined>;
|
|
193
|
+
/** Closes the runner's handle to a job that holds nothing any more, which frees the job. */
|
|
194
|
+
release(job: string, handle: number, deadline?: Deadline): void;
|
|
195
|
+
releaseAsync(job: string, handle: number, deadline?: Deadline): Promise<void>;
|
|
196
|
+
/**
|
|
197
|
+
* At the end of a run, each process still running in a job of a launch whose own process has ended, as a helper a test
|
|
198
|
+
* file left running is, with the launch's pid, leaving out console hosts; and each such launch's job that could not be
|
|
199
|
+
* read. A job given back meanwhile holds nothing, and one whose answer was lost may be gone too, its processes ended
|
|
200
|
+
* with its last handle; leaving the unread ones out of `straysAsync` names whatever they still hold there instead.
|
|
201
|
+
* `only`, when given, names the launches' jobs to read, such as one run's own among several a host holds at once.
|
|
202
|
+
*/
|
|
203
|
+
leftoversAsync(deadline?: Deadline, only?: ReadonlySet<string>): Promise<{
|
|
204
|
+
readonly found: readonly {
|
|
205
|
+
readonly root: number;
|
|
206
|
+
readonly process: SupervisedProcess;
|
|
207
|
+
}[];
|
|
208
|
+
readonly unread: readonly string[];
|
|
209
|
+
}>;
|
|
210
|
+
/**
|
|
211
|
+
* What the runner's job holds that no launch's job does and that nothing still running stands behind: a process left
|
|
212
|
+
* by one that had ended before its launch was held, which no launch's job took, and which runs until the runner ends.
|
|
213
|
+
* Console hosts are left out. `leaveOut` names launches' jobs to read as no launch's, so what they hold is named.
|
|
214
|
+
*/
|
|
215
|
+
strays(deadline?: Deadline): readonly SupervisedProcess[];
|
|
216
|
+
straysAsync(deadline?: Deadline, leaveOut?: readonly string[]): Promise<readonly SupervisedProcess[]>;
|
|
217
|
+
/**
|
|
218
|
+
* Sends Ctrl+C to the console of a launch's processes, or of `pid` among them, unless Retest itself is on that console;
|
|
219
|
+
* Ctrl+Break with `key: 'break'`, which a console program cannot be set to ignore.
|
|
220
|
+
*/
|
|
221
|
+
interrupt(job: string, options?: {
|
|
222
|
+
readonly pid?: number;
|
|
223
|
+
readonly key?: 'c' | 'break';
|
|
224
|
+
readonly deadline?: Deadline;
|
|
225
|
+
}): Interrupted;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* The supervisor's one line of output as a checked reply. Anything else, a second line included, is no answer.
|
|
229
|
+
*
|
|
230
|
+
* @example readReply('{"schemaVersion":1,"type":"ended","job":"Local\\\\retest-1-ab-2"}\n').type // 'ended'
|
|
231
|
+
*/
|
|
232
|
+
export declare function readReply(text: string): Reply;
|
|
233
|
+
/**
|
|
234
|
+
* Whether a process is the console host Windows starts beside a console program given a console of its own, as each test
|
|
235
|
+
* file's process, app server and media process is. It belongs to the programs on that console, runs nothing anyone gave
|
|
236
|
+
* it and ends a moment after the last of them, so it is never named as left running: a program still on its console is
|
|
237
|
+
* named itself.
|
|
238
|
+
*
|
|
239
|
+
* @example consoleHost({ pid: 7300, parentPid: 7200, startedAt: '1', image: 'C:\\Windows\\System32\\conhost.exe' }) // true
|
|
240
|
+
*/
|
|
241
|
+
export declare function consoleHost(process: SupervisedProcess): boolean;
|
|
242
|
+
/** Processes by pid and start, as a launch keeps what it has read as its own. */
|
|
243
|
+
export type ProcessRecords = ReadonlyMap<number, string>;
|
|
244
|
+
/**
|
|
245
|
+
* Whether a command line names `marker` as a folder of its own: between two separators, or after one at the end of a
|
|
246
|
+
* path, never as part of a longer name. Windows compares names whatever their case.
|
|
247
|
+
*
|
|
248
|
+
* @example namesFolder('firefox.exe --profile "C:\\Temp\\retest-firefox-1-a\\profile"', 'retest-firefox-1-a') // true
|
|
249
|
+
*/
|
|
250
|
+
export declare function namesFolder(commandLine: string | undefined, marker: string): boolean;
|
|
251
|
+
/** What a launch of a run has on record, and the markers that name its processes, for the run's end to tie strays by. */
|
|
252
|
+
export type LaunchRecord = {
|
|
253
|
+
readonly onRecord: () => ProcessRecords;
|
|
254
|
+
readonly markers: readonly string[];
|
|
255
|
+
};
|
|
256
|
+
/**
|
|
257
|
+
* Of the processes no launch's job holds and nothing running stands behind, those a run can tie to itself by the facts
|
|
258
|
+
* a launch's own reading goes by: each one on a launch's record by its pid and start, each one whose parent runs in this
|
|
259
|
+
* reading on such a record, and each one whose command line names a launch's marker. A record of any age is only ever
|
|
260
|
+
* its own process, so nothing is tied through a process that has ended.
|
|
261
|
+
*
|
|
262
|
+
* @example tiedTo([{ onRecord: () => new Map([[5001, '13437009000005001']]), markers: [] }], strays) // 5001, and what 5001 runs
|
|
263
|
+
*/
|
|
264
|
+
export declare function tiedTo(launches: readonly LaunchRecord[], strays: readonly SupervisedProcess[]): SupervisedProcess[];
|
|
265
|
+
/**
|
|
266
|
+
* A process left running, as cleanup names it; `when` says when it was seen, such as `after process 5000 ended`.
|
|
267
|
+
*
|
|
268
|
+
* @example stillRunningProblem({ pid: 6100, parentPid: 6050, startedAt: '1', image: 'C:\\Apps\\helper.exe' }, 'after process 5000 ended') // 'Process 6100 (helper.exe) is still running after process 5000 ended. Retest ends it when Retest exits.'
|
|
269
|
+
*/
|
|
270
|
+
export declare function stillRunningProblem(process: SupervisedProcess, when: string): string;
|
|
271
|
+
/** What cleanup says when it could not look for processes left running; `when` as for `stillRunningProblem`. */
|
|
272
|
+
export declare function leftoversUnreadProblem(error: unknown, when: string): string;
|
|
273
|
+
/**
|
|
274
|
+
* The command a process stands under when Windows would not name its executable. It has the shape the ownership rule
|
|
275
|
+
* reads as a command that cannot be read, so it is never compared as one.
|
|
276
|
+
*/
|
|
277
|
+
export declare const unreadableImage = "(unreadable)";
|
|
278
|
+
/**
|
|
279
|
+
* A launch's ownership readings on Windows, its job, what it has on record by pid and start (its job's members as its
|
|
280
|
+
* newest reading of the job found them, and those it holds by their parents as its newest reading of the runner's job
|
|
281
|
+
* left them), and its markers.
|
|
282
|
+
*/
|
|
283
|
+
export type JobOwnershipSystem = ProcessOwnershipSystem & LaunchRecord & {
|
|
284
|
+
readonly job: OwnedJob;
|
|
285
|
+
};
|
|
286
|
+
/**
|
|
287
|
+
* A launch's ownership readings on Windows: its job's own process list, where every member has the launch's pid as its
|
|
288
|
+
* group, a pid read with whether the job holds it, and the job's end, which ends every member at once. A job that was
|
|
289
|
+
* read empty holds nothing from then on, since only Retest puts processes in it and only when it is made, so its
|
|
290
|
+
* handle is given back and every later reading answers empty without asking.
|
|
291
|
+
*
|
|
292
|
+
* A process held by its parent, already in a job of its own when the launch was held, as the browser Firefox's Windows
|
|
293
|
+
* launcher starts is, belongs to the launch as well, with everything it starts while it runs: they are read from the
|
|
294
|
+
* runner's job as members, by the starts on record, through parents running in the same reading, and by `markers`, the
|
|
295
|
+
* names in a command line only this launch's processes carry, such as its profile folder.
|
|
296
|
+
*
|
|
297
|
+
* An empty job is not yet proof that the launch left nothing. A process whose own parent had ended before the launch
|
|
298
|
+
* was held cannot be tied to it, and stays in the runner's job only; so once the job is read empty, the runner's job is
|
|
299
|
+
* read too, and anything there that no launch's job holds and nothing running stands behind leaves the launch's
|
|
300
|
+
* cleanup unconfirmed, naming it. Each such process is named once in the host, for the first launch it is seen after.
|
|
301
|
+
*
|
|
302
|
+
* @example const ownership = new OwnedProcessGroup(child.pid, process.pid, jobSystem(supervisor, supervisor.adopt(child.pid)))
|
|
303
|
+
*/
|
|
304
|
+
export declare function jobSystem(supervisor: Supervisor, launch: HeldLaunch, options?: {
|
|
305
|
+
readonly markers?: readonly string[];
|
|
306
|
+
readonly lateParentMs?: number;
|
|
307
|
+
}): JobOwnershipSystem;
|
|
308
|
+
export {};
|
|
309
|
+
//# sourceMappingURL=process-supervisor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"process-supervisor.d.ts","sourceRoot":"","sources":["../../src/shared/process-supervisor.ts"],"names":[],"mappings":"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"}
|