diff --git a/packages/@ionic/cli-framework/package.json b/packages/@ionic/cli-framework/package.json index 0deebb3214..eca6fcb7f2 100644 --- a/packages/@ionic/cli-framework/package.json +++ b/packages/@ionic/cli-framework/package.json @@ -56,6 +56,7 @@ "stream-combiner2": "^1.1.1", "string-width": "^2.1.1", "strip-ansi": "^4.0.0", + "tree-kill": "1.2.0", "tslib": "^1.9.0", "untildify": "^3.0.2", "wrap-ansi": "^3.0.1", diff --git a/packages/@ionic/cli-framework/src/utils/process.ts b/packages/@ionic/cli-framework/src/utils/process.ts index f8e0a07f3a..f3da7bfaa9 100644 --- a/packages/@ionic/cli-framework/src/utils/process.ts +++ b/packages/@ionic/cli-framework/src/utils/process.ts @@ -1,5 +1,6 @@ import * as Debug from 'debug'; import * as lodash from 'lodash'; +import * as kill from 'tree-kill'; import { createCaseInsensitiveObject } from './object'; @@ -7,6 +8,19 @@ const debug = Debug('ionic:cli-framework:utils:process'); export const ERROR_TIMEOUT_REACHED = 'TIMEOUT_REACHED'; +export function killProcessTree(pid: number, signal: string | number = 'SIGTERM'): Promise { + return new Promise((resolve, reject) => { + kill(pid, signal, err => { + if (err) { + debug('error while killing process tree for %d: %o', pid, err); + return reject(err); + } + + resolve(); + }); + }); +} + /** * Creates an alternative implementation of `process.env` object. * diff --git a/packages/@ionic/cli-utils/src/lib/serve.ts b/packages/@ionic/cli-utils/src/lib/serve.ts index f1bd165022..8c7786924b 100644 --- a/packages/@ionic/cli-utils/src/lib/serve.ts +++ b/packages/@ionic/cli-utils/src/lib/serve.ts @@ -1,7 +1,7 @@ import { BaseError, LOGGER_LEVELS, NetworkInterface, OptionGroup, PromptModule, createPrefixedFormatter } from '@ionic/cli-framework'; import { fsReadJsonFile } from '@ionic/cli-framework/utils/fs'; import { findClosestOpenPort, getExternalIPv4Interfaces, isHostConnectable } from '@ionic/cli-framework/utils/network'; -import { onBeforeExit, processExit } from '@ionic/cli-framework/utils/process'; +import { killProcessTree, onBeforeExit, processExit } from '@ionic/cli-framework/utils/process'; import { str2num } from '@ionic/cli-framework/utils/string'; import chalk from 'chalk'; import * as Debug from 'debug'; @@ -529,7 +529,7 @@ export abstract class ServeCLI extends EventEmitter { p.on('error', errorHandler); p.on('close', closeHandler); - onBeforeExit(async () => p.kill()); + onBeforeExit(async () => killProcessTree(p.pid)); const log = this.e.log.clone(); log.setFormatter(createPrefixedFormatter(chalk.dim(`[${this.resolvedProgram === this.program ? this.prefix : this.resolvedProgram}]`))); diff --git a/packages/@ionic/cli-utils/src/lib/shell.ts b/packages/@ionic/cli-utils/src/lib/shell.ts index c3e5b25fe4..5ce0cefcb6 100644 --- a/packages/@ionic/cli-utils/src/lib/shell.ts +++ b/packages/@ionic/cli-utils/src/lib/shell.ts @@ -1,5 +1,5 @@ import { ERROR_SHELL_COMMAND_NOT_FOUND, LOGGER_LEVELS, ShellCommandError } from '@ionic/cli-framework'; -import { createProcessEnv, onBeforeExit } from '@ionic/cli-framework/utils/process'; +import { createProcessEnv, killProcessTree, onBeforeExit } from '@ionic/cli-framework/utils/process'; import { ShellCommand } from '@ionic/cli-framework/utils/shell'; import { combineStreams } from '@ionic/cli-framework/utils/streams'; import chalk from 'chalk'; @@ -69,7 +69,7 @@ export class Shell implements IShell { } if (killOnExit) { - onBeforeExit(async () => promise.p.kill()); + onBeforeExit(async () => killProcessTree(promise.p.pid)); } await promise; diff --git a/packages/ionic/src/commands/cordova/run.ts b/packages/ionic/src/commands/cordova/run.ts index 5448a59759..16123d2045 100644 --- a/packages/ionic/src/commands/cordova/run.ts +++ b/packages/ionic/src/commands/cordova/run.ts @@ -206,6 +206,7 @@ ${chalk.cyan('[1]')}: ${chalk.bold('https://ionicframework.com/docs/developer-re const ws = log.createWriteStream(LOGGER_LEVELS.INFO); await this.runCordova(filterArgumentsForCordova(metadata, options), { stream: ws }); + this.env.close(); // TODO: better way await sleepForever(); } else { if (options.build) { diff --git a/packages/ionic/src/commands/serve.ts b/packages/ionic/src/commands/serve.ts index 5105c93777..d88d580e4a 100644 --- a/packages/ionic/src/commands/serve.ts +++ b/packages/ionic/src/commands/serve.ts @@ -143,6 +143,7 @@ Try the ${chalk.green('--lab')} option to see multiple platforms at once.`; // TODO: use runner directly await serve({ config: this.env.config, log: this.env.log, prompt: this.env.prompt, shell: this.env.shell, project: this.project }, inputs, options); + this.env.close(); // TODO: better way await sleepForever(); } }