From 8850a35f9ea69ad065fc11f567bcdfd0e7ccbb93 Mon Sep 17 00:00:00 2001 From: Sanchit2662 Date: Wed, 14 Jan 2026 23:31:09 +0530 Subject: [PATCH] fix(backend): clean up process event listeners on backend stop Signed-off-by: Sanchit2662 --- .../src/wiring/BackendInitializer.ts | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/packages/backend-app-api/src/wiring/BackendInitializer.ts b/packages/backend-app-api/src/wiring/BackendInitializer.ts index c86fb0b29c..2d32306385 100644 --- a/packages/backend-app-api/src/wiring/BackendInitializer.ts +++ b/packages/backend-app-api/src/wiring/BackendInitializer.ts @@ -157,6 +157,8 @@ export class BackendInitializer { #serviceRegistry: ServiceRegistry; #registeredFeatures = new Array>(); #registeredFeatureLoaders = new Array(); + #unhandledRejectionHandler?: (reason: Error) => void; + #uncaughtExceptionHandler?: (error: Error) => void; constructor(defaultApiFactories: ServiceFactory[]) { this.#serviceRegistry = ServiceRegistry.create([...defaultApiFactories]); @@ -265,16 +267,18 @@ export class BackendInitializer { coreServices.rootLogger, 'root', ); - process.on('unhandledRejection', (reason: Error) => { + this.#unhandledRejectionHandler = (reason: Error) => { rootLogger ?.child({ type: 'unhandledRejection' }) ?.error('Unhandled rejection', reason); - }); - process.on('uncaughtException', error => { + }; + this.#uncaughtExceptionHandler = (error: Error) => { rootLogger ?.child({ type: 'uncaughtException' }) ?.error('Uncaught exception', error); - }); + }; + process.on('unhandledRejection', this.#unhandledRejectionHandler); + process.on('uncaughtException', this.#uncaughtExceptionHandler); } // Initialize all root scoped services @@ -490,6 +494,16 @@ export class BackendInitializer { // Once all plugin shutdown hooks are done, run root shutdown hooks. await rootLifecycleService.shutdown(); + + // Clean up process event listeners to prevent memory leaks and duplicate logging + if (this.#unhandledRejectionHandler) { + process.off('unhandledRejection', this.#unhandledRejectionHandler); + this.#unhandledRejectionHandler = undefined; + } + if (this.#uncaughtExceptionHandler) { + process.off('uncaughtException', this.#uncaughtExceptionHandler); + this.#uncaughtExceptionHandler = undefined; + } } // Bit of a hacky way to grab the lifecycle services, potentially find a nicer way to do this