From 243c9994d047f3102a9622d1a5cff42ef78515ee Mon Sep 17 00:00:00 2001 From: Alb11747 Date: Sun, 11 Oct 2026 13:14:36 -0400 Subject: [PATCH] fix(server): skip Windows cleanup for exited child processes (#16007) --- .../@effect__platform-node-shared@4.0.2.patch | 60 +++++++++++++++++++ pnpm-lock.yaml | 7 ++- pnpm-workspace.yaml | 1 + 3 files changed, 65 insertions(+), 3 deletions(-) create mode 100644 patches/@effect__platform-node-shared@4.0.2.patch diff --git a/patches/@effect__platform-node-shared@4.0.2.patch b/patches/@effect__platform-node-shared@4.0.2.patch new file mode 100644 index 0000000000000000000000000000000000000000..f08c7d096bc281ca93d98b7dd4206a13cacb74a1 --- /dev/null +++ b/patches/@effect__platform-node-shared@4.0.2.patch @@ -0,0 +1,60 @@ +diff --git a/dist/NodeChildProcessSpawner.js b/dist/NodeChildProcessSpawner.js +--- a/dist/NodeChildProcessSpawner.js ++++ b/dist/NodeChildProcessSpawner.js +@@ -44,9 +44,17 @@ + return false; + } + }; +-const taskkill = (childProcess, onExit = () => {}) => NodeChildProcess.execFile("taskkill", ["/pid", String(childProcess.pid), "/T", "/F"], { +- windowsHide: true +-}, onExit); ++const taskkill = (childProcess, onExit = () => {}) => { ++ // Once Node observes the leader's exit, taskkill /T cannot reclaim orphaned ++ // descendants through its PID, which may be reused. Skip stale-PID cleanup. ++ if (childProcess.exitCode !== null || childProcess.signalCode !== null) { ++ onExit(null); ++ return; ++ } ++ NodeChildProcess.execFile("taskkill", ["/pid", String(childProcess.pid), "/T", "/F"], { ++ windowsHide: true ++ }, onExit); ++}; + const make = /*#__PURE__*/Effect.gen(function* () { + const fs = yield* FileSystem.FileSystem; + const path = yield* Path.Path; +diff --git a/src/NodeChildProcessSpawner.ts b/src/NodeChildProcessSpawner.ts +--- a/src/NodeChildProcessSpawner.ts ++++ b/src/NodeChildProcessSpawner.ts +@@ -19,7 +19,9 @@ + * `forceKillAfter`, the wait is limited to one second and never escalates. + * With it, cleanup may take the configured duration plus a final one-second + * wait after `SIGKILL`. Zombie descendants can consume either full bound. On +- * Windows, `taskkill` terminates the tree and only the leader's exit is awaited. ++ * Windows, `taskkill` terminates the tree while the leader is running and only ++ * the leader's exit is awaited. Descendants that outlive the leader are not ++ * reclaimed by PID-based cleanup. + * + * POSIX cleanup targets a numeric process-group ID. If the group disappears + * and its ID is reused before cleanup, an unrelated group may be signalled. +@@ -99,13 +101,20 @@ + const taskkill = ( + childProcess: NodeChildProcess.ChildProcess, + onExit: (error: NodeChildProcess.ExecException | null) => void = () => {} +-) => ++) => { ++ // Once Node observes the leader's exit, taskkill /T cannot reclaim orphaned ++ // descendants through its PID, which may be reused. Skip stale-PID cleanup. ++ if (childProcess.exitCode !== null || childProcess.signalCode !== null) { ++ onExit(null) ++ return ++ } + NodeChildProcess.execFile( + "taskkill", + ["/pid", String(childProcess.pid!), "/T", "/F"], + { windowsHide: true }, + onExit + ) ++} + + const make = Effect.gen(function*() { + const fs = yield* FileSystem.FileSystem diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7e6efe075030e609b2e07ac4051457ce11b80768..f37cdc0ca1d37a7aba1c4c4325bdeda8f984889e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -144,6 +144,7 @@ packageExtensionsChecksum: sha256-FYDaKefjFcda1+vgiq8yMpZC4ehE5CyLi/bsCGLgTtY= patchedDependencies: '@clerk/expo@4.6.8': b8b22ab733de5bea846ad9e88046c10582352fe9ad86f314f368b2a823f0f281 + '@effect/platform-node-shared@4.0.2': 4efe73732a53b7d7bdbd9a9263eed06310fc387f870ef4a5e66429e9d1fd7cd9 '@effect/vitest@4.0.2': 595b7d26fb635caba9c3d39fcb189bb78a000192f8d3b60ead7174b310d1ade9 '@expo/metro-config@58.0.6': 90fa980e8b6480631fb2fbb04559834e3c612db40c550cd828f11be297d8d760 '@ff-labs/fff-node@0.11.0': 8956d6ed6938a1bce69b2d0b067ff258dd9ca753c5bbe7006f7b68f760ea3ad2 @@ -611,7 +612,7 @@ importers: version: 4.0.2(bufferutil@4.1.0)(effect@4.0.2(patch_hash=ec61ee307eaec3e17f757e0e6a16296ea4b7a8c3188df0c6ec5e66301fd78688))(redis@6.2.1)(utf-8-validate@6.0.6) '@effect/platform-node-shared': specifier: 4.0.2 - version: 4.0.2(bufferutil@4.1.0)(effect@4.0.2(patch_hash=ec61ee307eaec3e17f757e0e6a16296ea4b7a8c3188df0c6ec5e66301fd78688))(utf-8-validate@6.0.6) + version: 4.0.2(patch_hash=4efe73732a53b7d7bdbd9a9263eed06310fc387f870ef4a5e66429e9d1fd7cd9)(bufferutil@4.1.0)(effect@4.0.2(patch_hash=ec61ee307eaec3e17f757e0e6a16296ea4b7a8c3188df0c6ec5e66301fd78688))(utf-8-validate@6.0.6) '@ff-labs/fff-node': specifier: 0.11.0 version: 0.11.0(patch_hash=8956d6ed6938a1bce69b2d0b067ff258dd9ca753c5bbe7006f7b68f760ea3ad2) @@ -13838,7 +13839,7 @@ snapshots: transitivePeerDependencies: - encoding - '@effect/platform-node-shared@4.0.2(bufferutil@4.1.0)(effect@4.0.2(patch_hash=ec61ee307eaec3e17f757e0e6a16296ea4b7a8c3188df0c6ec5e66301fd78688))(utf-8-validate@6.0.6)': + '@effect/platform-node-shared@4.0.2(patch_hash=4efe73732a53b7d7bdbd9a9263eed06310fc387f870ef4a5e66429e9d1fd7cd9)(bufferutil@4.1.0)(effect@4.0.2(patch_hash=ec61ee307eaec3e17f757e0e6a16296ea4b7a8c3188df0c6ec5e66301fd78688))(utf-8-validate@6.0.6)': dependencies: '@types/ws': 8.18.2 effect: 4.0.2(patch_hash=ec61ee307eaec3e17f757e0e6a16296ea4b7a8c3188df0c6ec5e66301fd78688) @@ -13849,7 +13850,7 @@ snapshots: '@effect/platform-node@4.0.2(bufferutil@4.1.0)(effect@4.0.2(patch_hash=ec61ee307eaec3e17f757e0e6a16296ea4b7a8c3188df0c6ec5e66301fd78688))(redis@6.2.1)(utf-8-validate@6.0.6)': dependencies: - '@effect/platform-node-shared': 4.0.2(bufferutil@4.1.0)(effect@4.0.2(patch_hash=ec61ee307eaec3e17f757e0e6a16296ea4b7a8c3188df0c6ec5e66301fd78688))(utf-8-validate@6.0.6) + '@effect/platform-node-shared': 4.0.2(patch_hash=4efe73732a53b7d7bdbd9a9263eed06310fc387f870ef4a5e66429e9d1fd7cd9)(bufferutil@4.1.0)(effect@4.0.2(patch_hash=ec61ee307eaec3e17f757e0e6a16296ea4b7a8c3188df0c6ec5e66301fd78688))(utf-8-validate@6.0.6) effect: 4.0.2(patch_hash=ec61ee307eaec3e17f757e0e6a16296ea4b7a8c3188df0c6ec5e66301fd78688) redis: 6.2.1 undici: 8.11.2 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index edbfad72d8e62d07f69cea2320497eaa5d923ac4..3ffe4a41ee4492e7ac3d955bb6b2474814027a13 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -288,6 +288,7 @@ patchedDependencies: expo-blur@58.0.3: patches/expo-blur@58.0.3.patch expo-audio@58.0.4: patches/expo-audio@58.0.4.patch "@clerk/expo@4.6.8": patches/@clerk__expo@4.6.8.patch + "@effect/platform-node-shared@4.0.2": patches/@effect__platform-node-shared@4.0.2.patch "@effect/vitest@4.0.2": patches/@effect__vitest@4.0.2.patch "@expo/metro-config@58.0.6": patches/@expo__metro-config@58.0.6.patch expo-sharing@58.0.13: patches/expo-sharing@58.0.13.patch -- 2.54.0