fix: Explicitly exit CLI to prevent hanging subprocesses (#3083)

Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
This commit is contained in:
Haris Gušić
2025-10-27 06:03:10 +01:00
committed by GitHub
parent 5e886c35d5
commit a9624c0fff
7 changed files with 71 additions and 51 deletions

View File

@@ -11,7 +11,7 @@ export async function InstanceBootstrap() {
await Plugin.init()
Share.init()
Format.init()
LSP.init()
await LSP.init()
FileWatcher.init()
File.init()
}

View File

@@ -1,23 +1,26 @@
import { Log } from "@/util/log"
export namespace State {
interface Entry {
state: any
dispose?: (state: any) => Promise<void>
}
const entries = new Map<string, Map<any, Entry>>()
const log = Log.create({ service: "state" })
const recordsByKey = new Map<string, Map<any, Entry>>()
export function create<S>(root: () => string, init: () => S, dispose?: (state: Awaited<S>) => Promise<void>) {
return () => {
const key = root()
let collection = entries.get(key)
if (!collection) {
collection = new Map<string, Entry>()
entries.set(key, collection)
let entries = recordsByKey.get(key)
if (!entries) {
entries = new Map<string, Entry>()
recordsByKey.set(key, entries)
}
const exists = collection.get(init)
const exists = entries.get(init)
if (exists) return exists.state as S
const state = init()
collection.set(init, {
entries.set(init, {
state,
dispose,
})
@@ -26,9 +29,38 @@ export namespace State {
}
export async function dispose(key: string) {
for (const [_, entry] of entries.get(key)?.entries() ?? []) {
const entries = recordsByKey.get(key)
if (!entries) return
log.info("waiting for state disposal to complete", { key })
let disposalFinished = false
setTimeout(() => {
if (!disposalFinished) {
log.warn(
"state disposal is taking an unusually long time - if it does not complete in a reasonable time, please report this as a bug",
{ key },
)
}
}, 10000).unref()
const tasks: Promise<void>[] = []
for (const entry of entries.values()) {
if (!entry.dispose) continue
await entry.dispose(await entry.state)
const task = Promise.resolve(entry.state)
.then((state) => entry.dispose!(state))
.catch((error) => {
log.error("Error while disposing state:", { error, key })
})
tasks.push(task)
}
await Promise.all(tasks)
disposalFinished = true
log.info("state disposal completed", { key })
}
}