wait for whole session to exit when sigterm (#2620)

* wait for whole session to exit when sigterm

* fix lint

* rename poorly named variable
This commit is contained in:
Aiden McClelland
2024-05-16 19:54:36 -06:00
committed by GitHub
parent 0b8a142de0
commit 0ccbb52c1f
3 changed files with 59 additions and 19 deletions

View File

@@ -91,7 +91,7 @@ export type ServiceInterfaceType = "ui" | "p2p" | "api"
export type MainEffects = Effects & { _type: "main" }
export type Signals = NodeJS.Signals
export const SIGTERM: Signals = "SIGTERM"
export const SIGKILL: Signals = "SIGTERM"
export const SIGKILL: Signals = "SIGKILL"
export const NO_TIMEOUT = -1
function removeConstType<E>() {

View File

@@ -1,9 +1,9 @@
import { NO_TIMEOUT, SIGTERM } from "../StartSdk"
import { NO_TIMEOUT, SIGKILL, SIGTERM } from "../StartSdk"
import { SDKManifest } from "../manifest/ManifestTypes"
import { Effects, ValidIfNoStupidEscape } from "../types"
import { MountOptions, Overlay } from "../util/Overlay"
import { splitCommand } from "../util/splitCommand"
import { cpExecFile } from "./Daemons"
import { cpExecFile, cpExec } from "./Daemons"
export class CommandController {
private constructor(
@@ -74,11 +74,16 @@ export class CommandController {
try {
return await this.runningAnswer
} finally {
await cpExecFile("pkill", ["-9", "-s", String(this.pid)]).catch((_) => {})
if (this.pid !== undefined) {
await cpExecFile("pkill", ["-9", "-s", String(this.pid)]).catch(
(_) => {},
)
}
await this.overlay.destroy().catch((_) => {})
}
}
async term({ signal = SIGTERM, timeout = NO_TIMEOUT } = {}) {
if (this.pid === undefined) return
try {
await cpExecFile("pkill", [
`-${signal.replace("SIG", "")}`,
@@ -86,23 +91,58 @@ export class CommandController {
String(this.pid),
])
if (timeout > NO_TIMEOUT) {
const didTimeout = await Promise.race([
new Promise((resolve) => setTimeout(resolve, timeout)).then(
() => true,
),
this.runningAnswer.then(() => false),
])
if (didTimeout) {
await cpExecFile("pkill", [`-9`, "-s", String(this.pid)]).catch(
(_: any) => {},
)
}
} else {
await this.runningAnswer
const didTimeout = await waitSession(this.pid, timeout)
if (didTimeout) {
await cpExecFile("pkill", [`-9`, "-s", String(this.pid)]).catch(
(_) => {},
)
}
} finally {
await this.overlay.destroy()
}
}
}
function waitSession(
sid: number,
timeout = NO_TIMEOUT,
interval = 100,
): Promise<boolean> {
let nextInterval = interval * 2
if (timeout >= 0 && timeout < nextInterval) {
nextInterval = timeout
}
let nextTimeout = timeout
if (timeout > 0) {
if (timeout >= interval) {
nextTimeout -= interval
} else {
nextTimeout = 0
}
}
return new Promise((resolve, reject) => {
let next: NodeJS.Timeout | null = null
if (timeout !== 0) {
next = setTimeout(() => {
waitSession(sid, nextTimeout, nextInterval).then(resolve, reject)
}, interval)
}
cpExecFile("ps", [`--sid=${sid}`, "-o", "--pid="]).then(
(_) => {
if (timeout === 0) {
resolve(true)
}
},
(e) => {
if (next) {
clearTimeout(next)
}
if (typeof e === "object" && e && "code" in e && e.code) {
resolve(false)
} else {
reject(e)
}
},
)
})
}

View File

@@ -19,7 +19,7 @@ import { HealthDaemon } from "./HealthDaemon"
import { Daemon } from "./Daemon"
import { CommandController } from "./CommandController"
const cpExec = promisify(CP.exec)
export const cpExec = promisify(CP.exec)
export const cpExecFile = promisify(CP.execFile)
export type Ready = {
display: string | null