diff --git a/packages/vitest/package.json b/packages/vitest/package.json index cb1955bcdc50..b470174b0f1c 100644 --- a/packages/vitest/package.json +++ b/packages/vitest/package.json @@ -137,7 +137,7 @@ "std-env": "^3.3.1", "strip-literal": "^1.0.0", "tinybench": "^2.3.1", - "tinypool": "^0.3.1", + "tinypool": "^0.4.0", "tinyspy": "^1.0.2", "vite": "^3.0.0 || ^4.0.0", "vite-node": "workspace:*", diff --git a/packages/vitest/src/node/core.ts b/packages/vitest/src/node/core.ts index dd1918218d14..020c38f44de0 100644 --- a/packages/vitest/src/node/core.ts +++ b/packages/vitest/src/node/core.ts @@ -597,6 +597,7 @@ export class Vitest { setTimeout(() => { this.report('onProcessTimeout').then(() => { console.warn(`close timed out after ${this.config.teardownTimeout}ms`) + this.state.getProcessTimeoutCauses().forEach(cause => console.warn(cause)) process.exit() }) }, this.config.teardownTimeout).unref() diff --git a/packages/vitest/src/node/pools/threads.ts b/packages/vitest/src/node/pools/threads.ts index eadaf824fcbc..66c897343c34 100644 --- a/packages/vitest/src/node/pools/threads.ts +++ b/packages/vitest/src/node/pools/threads.ts @@ -54,6 +54,8 @@ export function createThreadsPool(ctx: Vitest, { execArgv, env }: PoolProcessOpt env, execArgv, + + terminateTimeout: ctx.config.teardownTimeout, } if (ctx.config.isolate) { @@ -87,6 +89,13 @@ export function createThreadsPool(ctx: Vitest, { execArgv, env }: PoolProcessOpt try { await pool.run(data, { transferList: [workerPort], name }) } + catch (error) { + // Worker got stuck and won't terminate - this may cause process to hang + if (error instanceof Error && /Failed to terminate worker/.test(error.message)) + ctx.state.addProcessTimeoutCause(`Failed to terminate worker while running ${files.join(', ')}.`) + else + throw error + } finally { port.close() workerPort.close() diff --git a/packages/vitest/src/node/state.ts b/packages/vitest/src/node/state.ts index 44315fb52b8b..fb6f8f4f0890 100644 --- a/packages/vitest/src/node/state.ts +++ b/packages/vitest/src/node/state.ts @@ -22,6 +22,7 @@ export class StateManager { idMap = new Map() taskFileMap = new WeakMap() errorsSet = new Set() + processTimeoutCauses = new Set() catchError(err: unknown, type: string): void { if (isAggregateError(err)) @@ -39,6 +40,14 @@ export class StateManager { return Array.from(this.errorsSet.values()) } + addProcessTimeoutCause(cause: string) { + this.processTimeoutCauses.add(cause) + } + + getProcessTimeoutCauses() { + return Array.from(this.processTimeoutCauses.values()) + } + getPaths() { return Array.from(this.pathsSet) } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 03704e2c0777..a375a100ede1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -890,7 +890,7 @@ importers: strip-ansi: ^7.0.1 strip-literal: ^1.0.0 tinybench: ^2.3.1 - tinypool: ^0.3.1 + tinypool: ^0.4.0 tinyspy: ^1.0.2 typescript: ^4.9.4 vite: ^4.0.0 @@ -917,7 +917,7 @@ importers: std-env: 3.3.1 strip-literal: 1.0.0 tinybench: 2.3.1 - tinypool: 0.3.1 + tinypool: 0.4.0 tinyspy: 1.0.2 vite: 4.0.0_@types+node@18.7.13 vite-node: link:../vite-node @@ -20168,8 +20168,8 @@ packages: resolution: {integrity: sha512-hGYWYBMPr7p4g5IarQE7XhlyWveh1EKhy4wUBS1LrHXCKYgvz+4/jCqgmJqZxxldesn05vccrtME2RLLZNW7iA==} dev: false - /tinypool/0.3.1: - resolution: {integrity: sha512-zLA1ZXlstbU2rlpA4CIeVaqvWq41MTWqLY3FfsAXgC8+f7Pk7zroaJQxDgxn1xNudKW6Kmj4808rPFShUlIRmQ==} + /tinypool/0.4.0: + resolution: {integrity: sha512-2ksntHOKf893wSAH4z/+JbPpi92esw8Gn9N2deXX+B0EO92hexAVI9GIZZPx7P5aYo5KULfeOSt3kMOmSOy6uA==} engines: {node: '>=14.0.0'} dev: false