diff --git a/src/server/processLauncher.ts b/src/server/processLauncher.ts index b19281a7a00d3..3a4d0df206b93 100644 --- a/src/server/processLauncher.ts +++ b/src/server/processLauncher.ts @@ -23,6 +23,7 @@ import { helper } from './helper'; import { Progress } from './progress'; import * as types from './types'; import { isUnderTest } from '../utils/utils'; +import { EventEmitter } from 'events'; export type Env = {[key: string]: string | number | boolean | undefined}; @@ -58,6 +59,26 @@ export async function gracefullyCloseAll() { await Promise.all(Array.from(gracefullyCloseSet).map(gracefullyClose => gracefullyClose().catch(e => {}))); } +class EventEmitterWrapper extends EventEmitter { + private _wrappedEvents: Set; + constructor(emitter: EventEmitter) { + super(); + this.setMaxListeners(0); + this._wrappedEvents = new Set(); + for (const method of ['addListener', 'on', 'once', 'prependListener', 'prependOnceListener'] as const) { + this[method] = (event: string | symbol, listener: (...args: any[]) => void) => { + if (!this._wrappedEvents.has(event)) { + this._wrappedEvents.add(event); + emitter.addListener(event, (...eventArgs) => this.emit(event, ...eventArgs)); + } + return super[method](event, listener); + }; + } + } +} + +const processWrapper = new EventEmitterWrapper(process); + export async function launchProcess(options: LaunchProcessOptions): Promise { const cleanup = () => helper.removeFolders(options.tempDirectories); @@ -115,9 +136,9 @@ export async function launchProcess(options: LaunchProcessOptions): Promise { + listeners.push(helper.addEventListener(processWrapper, 'SIGINT', () => { gracefullyClose().then(() => { // Give tests a chance to dispatch any async calls. if (isUnderTest()) @@ -128,9 +149,9 @@ export async function launchProcess(options: LaunchProcessOptions): Promise