fix(tsconnect): stop reporting a deliberate shutdown as a panic
The exit handler called onExit("Unexpected shutdown") whenever the Go
runtime exited. That was upstream's wording from when nothing could stop
the runtime, so every exit really was a panic. This fork added shutdown(),
so a clean teardown now reports itself as a crash to the panic handler
createIPN() hands to its callers.
Split the two cases. Before the IPN reaches the caller an exit is a
startup failure, and rejecting hands it back as an error rather than as a
side-channel callback. After that the caller holds the only shutdown
path, so report the exit without claiming it was unexpected.
Found in review of webnet/webnet#188.
Co-Authored-By: claude-opus-5 <noreply@anthropic.com>
This commit is contained in:
@@ -27,15 +27,29 @@ export async function startIPN(
|
|||||||
})
|
})
|
||||||
|
|
||||||
go.env[INIT_CALLBACK_ENV] = name
|
go.env[INIT_CALLBACK_ENV] = name
|
||||||
const exited = go.run(instance).then(() => {
|
|
||||||
|
// An exit before the IPN reaches the caller is a startup failure, and throwing
|
||||||
|
// hands it back as a rejection. Afterwards the caller holds the only shutdown
|
||||||
|
// path, so an exit is either that shutdown or a panic; report it either way,
|
||||||
|
// because the IPN is dead in both cases.
|
||||||
|
let handedOver = false
|
||||||
|
const exited: Promise<never> = go.run(instance).then(() => {
|
||||||
delete globals[name]
|
delete globals[name]
|
||||||
onExit("Unexpected shutdown")
|
if (handedOver) onExit("Go runtime exited")
|
||||||
throw new Error("Go runtime exited before the IPN was ready")
|
// Always reject: before the handover this is what fails the race below,
|
||||||
|
// and after it the race has settled, so nothing observes the rejection.
|
||||||
|
throw new Error(
|
||||||
|
handedOver
|
||||||
|
? "Go runtime exited"
|
||||||
|
: "Go runtime exited before the IPN was ready"
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
const [newIPN, terminate] = await Promise.race([ready, exited])
|
const [newIPN, terminate] = await Promise.race([ready, exited])
|
||||||
try {
|
try {
|
||||||
return await newIPN(config)
|
const ipn = await newIPN(config)
|
||||||
|
handedOver = true
|
||||||
|
return ipn
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// Nothing was built, so nothing can shut the runtime down. Exit it here and
|
// Nothing was built, so nothing can shut the runtime down. Exit it here and
|
||||||
// wait for it, or the page keeps a blocked runtime for a failed startup.
|
// wait for it, or the page keeps a blocked runtime for a failed startup.
|
||||||
|
|||||||
Reference in New Issue
Block a user