Skip to content

Commit 3a428a7

Browse files
committed
chore: US-028 add keepalive timer to Pi interactive sandbox code
1 parent e079fcd commit 3a428a7

1 file changed

Lines changed: 14 additions & 5 deletions

File tree

packages/secure-exec/tests/cli-tools/pi-interactive.test.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -219,8 +219,11 @@ function createRedirectingNetworkAdapter(getMockUrl: () => string): NetworkAdapt
219219
* Build sandbox code that loads Pi's main module in interactive mode.
220220
* Uses PI_MAIN instead of PI_CLI to avoid undici import issues in-VM.
221221
* API redirect is handled by the networkAdapter at the bridge level.
222-
* Uses ESM format (export {}) so V8 uses execute_module() which properly
223-
* handles top-level await — CJS execute_script() doesn't await promises.
222+
*
223+
* Uses ESM with dynamic import() but does NOT await main() — main()
224+
* starts the TUI loop which keeps the V8 event loop alive via pending
225+
* async bridge promises (_stdinRead, _scheduleTimer). This matches
226+
* how Pi's cli.js works: it calls main() without await.
224227
*/
225228
function buildPiInteractiveCode(): string {
226229
const flags = [
@@ -236,10 +239,16 @@ function buildPiInteractiveCode(): string {
236239
// Override process.argv for Pi CLI
237240
process.argv = ['node', 'pi', ${flags.map((f) => JSON.stringify(f)).join(', ')}];
238241
239-
// Import main.js and call main() — in interactive mode main() starts
240-
// the TUI and stays running until the user exits
242+
// Keepalive timer: prevents the V8 event loop from exiting before main()
243+
// makes its first async bridge call. The TLA promise is V8-native (not
244+
// bridge-tracked), so without a bridge-level pending promise, the sidecar's
245+
// run_event_loop() exits immediately after execute_module() returns.
246+
const _keepalive = setInterval(() => {}, 60000);
247+
248+
// Import main.js and start main() — in interactive mode main() starts
249+
// the TUI and stays running until the user exits.
241250
const { main } = await import(${JSON.stringify(PI_MAIN)});
242-
await main(process.argv.slice(2));
251+
main(process.argv.slice(2)).finally(() => clearInterval(_keepalive));
243252
`;
244253
}
245254

0 commit comments

Comments
 (0)