From d2004dfb9b9d9464820e5e85a2545a321c07704d Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Thu, 5 Oct 2023 12:43:30 +0100 Subject: [PATCH] fix: `createDevice` race condition Creating a second device would terminate the second device correctly, then delete the old one from the map, causing it to be leaked and go missing Co-authored-by: Johan Nyman --- packages/timeline-state-resolver/src/conductor.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/packages/timeline-state-resolver/src/conductor.ts b/packages/timeline-state-resolver/src/conductor.ts index c93c5f757f..a22c1cb845 100644 --- a/packages/timeline-state-resolver/src/conductor.ts +++ b/packages/timeline-state-resolver/src/conductor.ts @@ -418,8 +418,8 @@ export class Conductor extends EventEmitter { options?: { signal?: AbortSignal } ): Promise>> { let newDevice: DeviceContainer> | undefined - const throwIfAborted = () => this.throwIfAborted(options?.signal, deviceId, 'creation') try { + const throwIfAborted = () => this.throwIfAborted(options?.signal, deviceId, 'creation') if (this.devices.has(deviceId)) { throw new Error(`Device "${deviceId}" already exists when creating device`) } @@ -441,7 +441,7 @@ export class Conductor extends EventEmitter { if (!newDevicePromise) { const type: any = deviceOptions.type - return Promise.reject(`No matching device type for "${type}" ("${DeviceType[type]}") found in conductor`) + throw new Error(`No matching device type for "${type}" ("${DeviceType[type]}") found in conductor`) } newDevice = await makeImmediatelyAbortable(async () => { @@ -466,15 +466,16 @@ export class Conductor extends EventEmitter { throw new Error(`Device "${deviceId}" already exists when creating device`) } throwIfAborted() - this.devices.set(deviceId, newDevice) - - return newDevice } catch (e) { await this.terminateUnwantedDevice(newDevice) - this.devices.delete(deviceId) + this.emit('error', 'conductor.createDevice', e) - return Promise.reject(e) + throw e } + + this.devices.set(deviceId, newDevice) + + return newDevice } private throwIfAborted(signal: AbortSignal | undefined, deviceId: string, action: string) {