From d632c770b92160aeaa15b9c63ce1cc071ce0b0cc Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Mon, 22 Nov 2021 15:33:11 +0100 Subject: [PATCH 1/4] Adopt `queueMicrotask` (#133173) --- src/vs/base/parts/ipc/common/ipc.net.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/vs/base/parts/ipc/common/ipc.net.ts b/src/vs/base/parts/ipc/common/ipc.net.ts index 6229c073c7a..4a708e614fa 100644 --- a/src/vs/base/parts/ipc/common/ipc.net.ts +++ b/src/vs/base/parts/ipc/common/ipc.net.ts @@ -6,7 +6,6 @@ import { VSBuffer } from 'vs/base/common/buffer'; import { Emitter, Event } from 'vs/base/common/event'; import { Disposable, dispose, IDisposable } from 'vs/base/common/lifecycle'; -import * as platform from 'vs/base/common/platform'; import { IIPCLogger, IMessagePassingProtocol, IPCClient } from 'vs/base/parts/ipc/common/ipc'; export const enum SocketCloseEventType { @@ -369,7 +368,7 @@ class ProtocolWriter { private _writeSoon(header: VSBuffer, data: VSBuffer): void { if (this._bufferAdd(header, data)) { - platform.setImmediate(() => { + queueMicrotask(() => { this._writeNow(); }); } From d27ef519053e7187e776d830cf3628c6bcd0de93 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Mon, 22 Nov 2021 15:53:24 +0100 Subject: [PATCH 2/4] Use `setTimeout` instead of `queueMicrotask` --- src/vs/base/parts/ipc/common/ipc.net.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/base/parts/ipc/common/ipc.net.ts b/src/vs/base/parts/ipc/common/ipc.net.ts index 4a708e614fa..b9d8a0ed064 100644 --- a/src/vs/base/parts/ipc/common/ipc.net.ts +++ b/src/vs/base/parts/ipc/common/ipc.net.ts @@ -368,7 +368,7 @@ class ProtocolWriter { private _writeSoon(header: VSBuffer, data: VSBuffer): void { if (this._bufferAdd(header, data)) { - queueMicrotask(() => { + setTimeout(() => { this._writeNow(); }); } From 187ccb8ec44e147d99c179c57b0ed5f3daba59bd Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Mon, 22 Nov 2021 20:47:27 +0100 Subject: [PATCH 3/4] The second argument of `setTimeout` is optional --- src/vs/base/test/common/timeTravelScheduler.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/base/test/common/timeTravelScheduler.ts b/src/vs/base/test/common/timeTravelScheduler.ts index 1f78d83359a..9c2ae28a425 100644 --- a/src/vs/base/test/common/timeTravelScheduler.ts +++ b/src/vs/base/test/common/timeTravelScheduler.ts @@ -263,7 +263,7 @@ export const originalGlobalValues = { Date: globalThis.Date, }; -function setTimeout(scheduler: Scheduler, handler: TimerHandler, timeout: number): IDisposable { +function setTimeout(scheduler: Scheduler, handler: TimerHandler, timeout: number = 0): IDisposable { if (typeof handler === 'string') { throw new Error('String handler args should not be used and are not supported'); } @@ -324,7 +324,7 @@ function setInterval(scheduler: Scheduler, handler: TimerHandler, interval: numb } function overwriteGlobals(scheduler: Scheduler): IDisposable { - globalThis.setTimeout = ((handler: TimerHandler, timeout: number) => setTimeout(scheduler, handler, timeout)) as any; + globalThis.setTimeout = ((handler: TimerHandler, timeout?: number) => setTimeout(scheduler, handler, timeout)) as any; globalThis.clearTimeout = (timeoutId: any) => { if (typeof timeoutId === 'object' && timeoutId && 'dispose' in timeoutId) { timeoutId.dispose(); From 954ce2c3f484563de4fdb2f7451729b2182f96c3 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 23 Nov 2021 10:31:46 +0100 Subject: [PATCH 4/4] proper await exit --- test/automation/src/code.ts | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/test/automation/src/code.ts b/test/automation/src/code.ts index 8deb024b4ae..2b3ebec4c0e 100644 --- a/test/automation/src/code.ts +++ b/test/automation/src/code.ts @@ -69,7 +69,7 @@ async function connect(connectDriver: typeof connectElectronDriver, child: cp.Ch while (true) { try { const { client, driver } = await connectDriver(outPath, handlePath); - return new Code(client, driver, logger); + return new Code(client, driver, logger, child?.pid); } catch (err) { if (++errCount > 50) { if (child) { @@ -254,7 +254,8 @@ export class Code { constructor( private client: IDisposable, driver: IDriver, - readonly logger: Logger + readonly logger: Logger, + private readonly pid: number | undefined ) { this.driver = new Proxy(driver, { get(target, prop, receiver) { @@ -295,9 +296,27 @@ export class Code { } async exit(): Promise { - const veto = await this.driver.exitApplication(); - if (veto === true) { - throw new Error('Code exit was blocked by a veto.'); + const exitPromise = this.driver.exitApplication(); + + // If we know the `pid`, use that to await the + // process to terminate (desktop). + const pid = this.pid; + if (typeof pid === 'number') { + await (async () => { + while (true) { + try { + process.kill(pid, 0); // throws an exception if the main process doesn't exist anymore. + await new Promise(c => setTimeout(c, 100)); + } catch (error) { + return; + } + } + })(); + } + + // Otherwise await the exit promise (web). + else { + await exitPromise; } }