mirror of
https://gitee.com/zhangsken/opencode.git
synced 2026-10-16 10:30:01 +08:00
refactor(util): share process stop policy (#45725)
This commit is contained in:
@@ -244,11 +244,11 @@ describe("cross-spawn spawner", () => {
|
||||
)
|
||||
|
||||
fx.effect(
|
||||
"kills a child when scope exits",
|
||||
"uses the configured kill signal when scope exits",
|
||||
Effect.gen(function* () {
|
||||
const pid = yield* Effect.scoped(
|
||||
Effect.gen(function* () {
|
||||
const handle = yield* js("setInterval(() => {}, 10_000)")
|
||||
const handle = yield* js("setInterval(() => {}, 10_000)", { killSignal: "SIGKILL" })
|
||||
return Number(handle.pid)
|
||||
}),
|
||||
)
|
||||
|
||||
@@ -321,6 +321,22 @@ const makeCrossSpawnSpawner = Effect.gen(function* () {
|
||||
return Effect.fail(toPlatformError("kill", new Error("Failed to kill child process"), command))
|
||||
})
|
||||
|
||||
const stop = (
|
||||
command: ChildProcess.StandardCommand,
|
||||
proc: NodeChildProcess.ChildProcess,
|
||||
exit: ExitSignal,
|
||||
opts: ChildProcess.KillOptions | undefined,
|
||||
) => {
|
||||
const send = (signal: NodeJS.Signals) =>
|
||||
Effect.catch(killGroup(command, proc, signal), () => killOne(command, proc, signal))
|
||||
const attempt = send(opts?.killSignal ?? "SIGTERM").pipe(Effect.andThen(Deferred.await(exit)), Effect.asVoid)
|
||||
if (!opts?.forceKillAfter) return attempt
|
||||
return Effect.timeoutOrElse(attempt, {
|
||||
duration: opts.forceKillAfter,
|
||||
orElse: () => send("SIGKILL").pipe(Effect.andThen(Deferred.await(exit)), Effect.asVoid),
|
||||
})
|
||||
}
|
||||
|
||||
const timeout =
|
||||
(
|
||||
proc: NodeChildProcess.ChildProcess,
|
||||
@@ -388,17 +404,7 @@ const makeCrossSpawnSpawner = Effect.gen(function* () {
|
||||
if (code !== 0 && Predicate.isNotNull(code)) return yield* Effect.ignore(kill(killGroup))
|
||||
return yield* Effect.void
|
||||
}
|
||||
const send = (s: NodeJS.Signals) =>
|
||||
Effect.catch(killGroup(command, proc, s), () => killOne(command, proc, s))
|
||||
const sig = command.options.killSignal ?? "SIGTERM"
|
||||
const attempt = send(sig).pipe(Effect.andThen(Deferred.await(signal)), Effect.asVoid)
|
||||
const escalated = command.options.forceKillAfter
|
||||
? Effect.timeoutOrElse(attempt, {
|
||||
duration: command.options.forceKillAfter,
|
||||
orElse: () => send("SIGKILL").pipe(Effect.andThen(Deferred.await(signal)), Effect.asVoid),
|
||||
})
|
||||
: attempt
|
||||
return yield* Effect.ignore(escalated)
|
||||
return yield* Effect.ignore(stop(command, proc, signal, command.options))
|
||||
}),
|
||||
)
|
||||
|
||||
@@ -424,17 +430,7 @@ const makeCrossSpawnSpawner = Effect.gen(function* () {
|
||||
),
|
||||
)
|
||||
}),
|
||||
kill: (opts?: ChildProcess.KillOptions) => {
|
||||
const sig = opts?.killSignal ?? "SIGTERM"
|
||||
const send = (s: NodeJS.Signals) =>
|
||||
Effect.catch(killGroup(command, proc, s), () => killOne(command, proc, s))
|
||||
const attempt = send(sig).pipe(Effect.andThen(Deferred.await(signal)), Effect.asVoid)
|
||||
if (!opts?.forceKillAfter) return attempt
|
||||
return Effect.timeoutOrElse(attempt, {
|
||||
duration: opts.forceKillAfter,
|
||||
orElse: () => send("SIGKILL").pipe(Effect.andThen(Deferred.await(signal)), Effect.asVoid),
|
||||
})
|
||||
},
|
||||
kill: (opts?: ChildProcess.KillOptions) => stop(command, proc, signal, opts),
|
||||
unref: Effect.sync(() => {
|
||||
if (ref) {
|
||||
proc.unref()
|
||||
|
||||
Reference in New Issue
Block a user