mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-26 10:21:52 +00:00
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:
@@ -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>() {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
},
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user