Skip to content

Commit 58ef159

Browse files
committed
fix: wait for tunnel process close events
1 parent e3b5fcd commit 58ef159

1 file changed

Lines changed: 23 additions & 15 deletions

File tree

packages/api/src/services/panel-cloudflare-tunnel.ts

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ type PanelCloudflareTunnelRecord = {
1717
readonly homeDir: string
1818
logLines: ReadonlyArray<string>
1919
process: ChildProcess | null
20+
processClosed: boolean
2021
session: PanelCloudflareTunnelSession
2122
stderrRemainder: string
2223
stopFiber: Fiber.RuntimeFiber<PanelCloudflareTunnelSession> | null
@@ -150,6 +151,7 @@ const createStartingRecord = (
150151
homeDir,
151152
logLines: [],
152153
process: null,
154+
processClosed: false,
153155
session: {
154156
error: null,
155157
id,
@@ -199,12 +201,16 @@ const finishStoppedRecord = (
199201
return session
200202
}
201203

202-
const waitForChildClose = (child: ChildProcess): Effect.Effect<void> => {
203-
if (child.exitCode !== null || child.signalCode !== null) {
204+
const waitForChildClose = (
205+
record: PanelCloudflareTunnelRecord,
206+
child: ChildProcess
207+
): Effect.Effect<void> => {
208+
if (record.processClosed) {
204209
return Effect.void
205210
}
206211

207212
return Effect.async((resume) => {
213+
const alreadyExited = child.exitCode !== null || child.signalCode !== null
208214
let completed = false
209215
let killTimer: ReturnType<typeof setTimeout> | null = null
210216
const complete = (): void => {
@@ -214,7 +220,6 @@ const waitForChildClose = (child: ChildProcess): Effect.Effect<void> => {
214220
completed = true
215221
child.off("close", complete)
216222
child.off("error", complete)
217-
child.off("exit", complete)
218223
if (killTimer !== null) {
219224
clearTimeout(killTimer)
220225
}
@@ -223,25 +228,26 @@ const waitForChildClose = (child: ChildProcess): Effect.Effect<void> => {
223228

224229
child.once("close", complete)
225230
child.once("error", complete)
226-
child.once("exit", complete)
227-
if (!child.killed) {
231+
if (!alreadyExited && !child.killed) {
228232
try {
229233
child.kill("SIGTERM")
230234
} catch {
231235
complete()
232236
return
233237
}
234238
}
235-
killTimer = setTimeout(() => {
236-
try {
237-
if (child.exitCode === null && child.signalCode === null) {
238-
child.kill("SIGKILL")
239+
if (!alreadyExited) {
240+
killTimer = setTimeout(() => {
241+
try {
242+
if (child.exitCode === null && child.signalCode === null) {
243+
child.kill("SIGKILL")
244+
}
245+
} catch {
246+
complete()
239247
}
240-
} catch {
241-
complete()
242-
}
243-
}, 2_000)
244-
killTimer.unref()
248+
}, 2_000)
249+
killTimer.unref()
250+
}
245251
})
246252
}
247253

@@ -255,7 +261,7 @@ const stopRecord = (
255261

256262
const child = record.process
257263
record.stopping = true
258-
const stopFiber = Effect.runFork((child === null ? Effect.void : waitForChildClose(child)).pipe(
264+
const stopFiber = Effect.runFork((child === null ? Effect.void : waitForChildClose(record, child)).pipe(
259265
Effect.map(() => finishStoppedRecord(record, error))
260266
))
261267
record.stopFiber = stopFiber
@@ -277,6 +283,7 @@ const attachProcessHandlers = (
277283
child: ChildProcess
278284
): void => {
279285
record.process = child
286+
record.processClosed = false
280287
child.stdout?.on("data", (chunk: Buffer) => {
281288
consumeChunk(record, "stdout", chunk)
282289
})
@@ -287,6 +294,7 @@ const attachProcessHandlers = (
287294
runStopRecord(record, `cloudflared failed to start: ${error.message}`)
288295
})
289296
child.on("close", (exitCode, signal) => {
297+
record.processClosed = true
290298
flushRemainder(record, "stdout")
291299
flushRemainder(record, "stderr")
292300
if (record.stopping || record.session.status === "stopped" || record.session.status === "failed") {

0 commit comments

Comments
 (0)