fix(watcher): ensure child processes are killed and awaited during shutdown; improve cleanup handlers; bump smartshell dependency to ^3.3.2
This commit is contained in:
@@ -1,5 +1,13 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 2026-03-03 - 3.2.1 - fix(watcher)
|
||||||
|
ensure child processes are killed and awaited during shutdown; improve cleanup handlers; bump smartshell dependency to ^3.3.2
|
||||||
|
|
||||||
|
- Await child process kill() calls in restart and stop to avoid race conditions and ensure proper termination.
|
||||||
|
- Add last-resort synchronous SIGKILL in process 'exit' handler to terminate orphaned child processes.
|
||||||
|
- Make SIGINT and timeout handlers async and await stop() to perform a clean shutdown before exiting.
|
||||||
|
- Bump @push.rocks/smartshell from ^3.3.0 to ^3.3.2 in package.json.
|
||||||
|
|
||||||
## 2026-02-24 - 3.2.0 - feat(bundle)
|
## 2026-02-24 - 3.2.0 - feat(bundle)
|
||||||
add configurable bundle output modes and bundler options (support base64ts, production builds, includeFiles, maxLineLength) and route non-default outputs to a CustomBundleHandler
|
add configurable bundle output modes and bundler options (support base64ts, production builds, includeFiles, maxLineLength) and route non-default outputs to a CustomBundleHandler
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
"@push.rocks/smartinteract": "^2.0.16",
|
"@push.rocks/smartinteract": "^2.0.16",
|
||||||
"@push.rocks/smartlog": "^3.1.10",
|
"@push.rocks/smartlog": "^3.1.10",
|
||||||
"@push.rocks/smartlog-destination-local": "^9.0.2",
|
"@push.rocks/smartlog-destination-local": "^9.0.2",
|
||||||
"@push.rocks/smartshell": "^3.3.0",
|
"@push.rocks/smartshell": "^3.3.2",
|
||||||
"@push.rocks/smartwatch": "^6.3.0",
|
"@push.rocks/smartwatch": "^6.3.0",
|
||||||
"@push.rocks/taskbuffer": "^4.2.0"
|
"@push.rocks/taskbuffer": "^4.2.0"
|
||||||
},
|
},
|
||||||
|
|||||||
30
pnpm-lock.yaml
generated
30
pnpm-lock.yaml
generated
@@ -45,8 +45,8 @@ importers:
|
|||||||
specifier: ^9.0.2
|
specifier: ^9.0.2
|
||||||
version: 9.0.2
|
version: 9.0.2
|
||||||
'@push.rocks/smartshell':
|
'@push.rocks/smartshell':
|
||||||
specifier: ^3.3.0
|
specifier: ^3.3.2
|
||||||
version: 3.3.0
|
version: 3.3.2
|
||||||
'@push.rocks/smartwatch':
|
'@push.rocks/smartwatch':
|
||||||
specifier: ^6.3.0
|
specifier: ^6.3.0
|
||||||
version: 6.3.0
|
version: 6.3.0
|
||||||
@@ -972,12 +972,12 @@ packages:
|
|||||||
'@push.rocks/smarterror@2.0.1':
|
'@push.rocks/smarterror@2.0.1':
|
||||||
resolution: {integrity: sha512-iCcH1D8tlDJgMFsaJ6lhdOTKhbU0KoprNv9MRP9o7691QOx4JEDXiHtr/lNtxVo8BUtdb9CF6kazaknO9KuORA==}
|
resolution: {integrity: sha512-iCcH1D8tlDJgMFsaJ6lhdOTKhbU0KoprNv9MRP9o7691QOx4JEDXiHtr/lNtxVo8BUtdb9CF6kazaknO9KuORA==}
|
||||||
|
|
||||||
'@push.rocks/smartexit@1.0.23':
|
|
||||||
resolution: {integrity: sha512-WmwKYcwbHBByoABhHHB+PAjr5475AtD/xBh1mDcqPrFsOOUOZq3BBUdpq25wI3ccu/SZB5IwaimiVzadls6HkA==}
|
|
||||||
|
|
||||||
'@push.rocks/smartexit@1.1.0':
|
'@push.rocks/smartexit@1.1.0':
|
||||||
resolution: {integrity: sha512-GD8VLIbxQuwvhPXwK4eH162XAYSj+M3wGKWGNO3i1iY4bj8P3BARcgsWx6/ntN3aCo5ygWtrevrfD5iecYY2Ng==}
|
resolution: {integrity: sha512-GD8VLIbxQuwvhPXwK4eH162XAYSj+M3wGKWGNO3i1iY4bj8P3BARcgsWx6/ntN3aCo5ygWtrevrfD5iecYY2Ng==}
|
||||||
|
|
||||||
|
'@push.rocks/smartexit@1.1.1':
|
||||||
|
resolution: {integrity: sha512-UwcVJbp7vzzDM9RQmnfTaVOJ+DK127lAC5gwyfKU2GfPAv0Jng62Sv601otP+jnly9nRt5fUuttNHDl34Mjn3g==}
|
||||||
|
|
||||||
'@push.rocks/smartexpect@2.5.0':
|
'@push.rocks/smartexpect@2.5.0':
|
||||||
resolution: {integrity: sha512-yoyuCoQ3tTiAriuvF+/09fNbVfFnacudL2SwHSzPhX/ugaE7VTSWXQ9A34eKOWvil0MPyDcOY36fVZDxvrPd8A==}
|
resolution: {integrity: sha512-yoyuCoQ3tTiAriuvF+/09fNbVfFnacudL2SwHSzPhX/ugaE7VTSWXQ9A34eKOWvil0MPyDcOY36fVZDxvrPd8A==}
|
||||||
|
|
||||||
@@ -1098,8 +1098,8 @@ packages:
|
|||||||
'@push.rocks/smartserve@2.0.1':
|
'@push.rocks/smartserve@2.0.1':
|
||||||
resolution: {integrity: sha512-YQb2qexfCzCqOlLWBBXKMg6xG4zahCPAxomz/KEKAwHtW6wMTtuHKSTSkRTQ0vl9jssLMAmRz2OyafiL9XGJXQ==}
|
resolution: {integrity: sha512-YQb2qexfCzCqOlLWBBXKMg6xG4zahCPAxomz/KEKAwHtW6wMTtuHKSTSkRTQ0vl9jssLMAmRz2OyafiL9XGJXQ==}
|
||||||
|
|
||||||
'@push.rocks/smartshell@3.3.0':
|
'@push.rocks/smartshell@3.3.2':
|
||||||
resolution: {integrity: sha512-m0w618H6YBs+vXGz1CgS4nPi5CUAnqRtckcS9/koGwfcIx1IpjqmiP47BoCTbdgcv0IPUxQVBG1IXTHPuZ8Z5g==}
|
resolution: {integrity: sha512-xDakRUYBO/WDXlBvS2IbreAvXke/oUul2hcna953a1Bv5gMPOSVBVFsFIaUEqTzAQ5/1YjjEhbnjPeXq87jgkA==}
|
||||||
|
|
||||||
'@push.rocks/smartsitemap@2.0.4':
|
'@push.rocks/smartsitemap@2.0.4':
|
||||||
resolution: {integrity: sha512-76dYWG/o/EjV4vYCK7ZKM35T9xgrI+oHEiiIE6E2MDaFIU6QnSfciTfbscH5nc0vxx8Ah+I0HPEJO94BM2S39w==}
|
resolution: {integrity: sha512-76dYWG/o/EjV4vYCK7ZKM35T9xgrI+oHEiiIE6E2MDaFIU6QnSfciTfbscH5nc0vxx8Ah+I0HPEJO94BM2S39w==}
|
||||||
@@ -5627,7 +5627,7 @@ snapshots:
|
|||||||
'@push.rocks/smartnpm': 2.0.6
|
'@push.rocks/smartnpm': 2.0.6
|
||||||
'@push.rocks/smartpath': 6.0.0
|
'@push.rocks/smartpath': 6.0.0
|
||||||
'@push.rocks/smartrequest': 5.0.1
|
'@push.rocks/smartrequest': 5.0.1
|
||||||
'@push.rocks/smartshell': 3.3.0
|
'@push.rocks/smartshell': 3.3.2
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@nuxt/kit'
|
- '@nuxt/kit'
|
||||||
- aws-crt
|
- aws-crt
|
||||||
@@ -5640,7 +5640,7 @@ snapshots:
|
|||||||
'@git.zone/tsrun@2.0.1':
|
'@git.zone/tsrun@2.0.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@push.rocks/smartfile': 13.1.2
|
'@push.rocks/smartfile': 13.1.2
|
||||||
'@push.rocks/smartshell': 3.3.0
|
'@push.rocks/smartshell': 3.3.2
|
||||||
tsx: 4.21.0
|
tsx: 4.21.0
|
||||||
|
|
||||||
'@git.zone/tstest@3.1.8(@aws-sdk/credential-providers@3.855.0)(@push.rocks/smartserve@2.0.1)(socks@2.8.7)(typescript@5.9.3)':
|
'@git.zone/tstest@3.1.8(@aws-sdk/credential-providers@3.855.0)(@push.rocks/smartserve@2.0.1)(socks@2.8.7)(typescript@5.9.3)':
|
||||||
@@ -5665,7 +5665,7 @@ snapshots:
|
|||||||
'@push.rocks/smartpromise': 4.2.3
|
'@push.rocks/smartpromise': 4.2.3
|
||||||
'@push.rocks/smartrequest': 5.0.1
|
'@push.rocks/smartrequest': 5.0.1
|
||||||
'@push.rocks/smarts3': 3.0.3
|
'@push.rocks/smarts3': 3.0.3
|
||||||
'@push.rocks/smartshell': 3.3.0
|
'@push.rocks/smartshell': 3.3.2
|
||||||
'@push.rocks/smarttime': 4.1.1
|
'@push.rocks/smarttime': 4.1.1
|
||||||
'@types/ws': 8.18.1
|
'@types/ws': 8.18.1
|
||||||
figures: 6.1.0
|
figures: 6.1.0
|
||||||
@@ -6307,14 +6307,14 @@ snapshots:
|
|||||||
clean-stack: 1.3.0
|
clean-stack: 1.3.0
|
||||||
make-error-cause: 2.3.0
|
make-error-cause: 2.3.0
|
||||||
|
|
||||||
'@push.rocks/smartexit@1.0.23':
|
'@push.rocks/smartexit@1.1.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@push.rocks/lik': 6.2.2
|
'@push.rocks/lik': 6.2.2
|
||||||
'@push.rocks/smartdelay': 3.0.5
|
'@push.rocks/smartdelay': 3.0.5
|
||||||
'@push.rocks/smartpromise': 4.2.3
|
'@push.rocks/smartpromise': 4.2.3
|
||||||
tree-kill: 1.2.2
|
tree-kill: 1.2.2
|
||||||
|
|
||||||
'@push.rocks/smartexit@1.1.0':
|
'@push.rocks/smartexit@1.1.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@push.rocks/lik': 6.2.2
|
'@push.rocks/lik': 6.2.2
|
||||||
'@push.rocks/smartdelay': 3.0.5
|
'@push.rocks/smartdelay': 3.0.5
|
||||||
@@ -6579,7 +6579,7 @@ snapshots:
|
|||||||
'@push.rocks/smartpuppeteer@2.0.5(typescript@5.9.3)':
|
'@push.rocks/smartpuppeteer@2.0.5(typescript@5.9.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@push.rocks/smartdelay': 3.0.5
|
'@push.rocks/smartdelay': 3.0.5
|
||||||
'@push.rocks/smartshell': 3.3.0
|
'@push.rocks/smartshell': 3.3.2
|
||||||
puppeteer: 24.36.0(typescript@5.9.3)
|
puppeteer: 24.36.0(typescript@5.9.3)
|
||||||
tree-kill: 1.2.2
|
tree-kill: 1.2.2
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
@@ -6650,10 +6650,10 @@ snapshots:
|
|||||||
- bufferutil
|
- bufferutil
|
||||||
- utf-8-validate
|
- utf-8-validate
|
||||||
|
|
||||||
'@push.rocks/smartshell@3.3.0':
|
'@push.rocks/smartshell@3.3.2':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@push.rocks/smartdelay': 3.0.5
|
'@push.rocks/smartdelay': 3.0.5
|
||||||
'@push.rocks/smartexit': 1.0.23
|
'@push.rocks/smartexit': 1.1.1
|
||||||
'@push.rocks/smartpromise': 4.2.3
|
'@push.rocks/smartpromise': 4.2.3
|
||||||
'@types/which': 3.0.4
|
'@types/which': 3.0.4
|
||||||
tree-kill: 1.2.2
|
tree-kill: 1.2.2
|
||||||
|
|||||||
@@ -3,6 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@git.zone/tswatch',
|
name: '@git.zone/tswatch',
|
||||||
version: '3.2.0',
|
version: '3.2.1',
|
||||||
description: 'A development tool for automatically watching and re-compiling TypeScript projects upon detecting file changes, enhancing developer workflows.'
|
description: 'A development tool for automatically watching and re-compiling TypeScript projects upon detecting file changes, enhancing developer workflows.'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -154,7 +154,7 @@ export class Watcher {
|
|||||||
if (this.options.commandToExecute) {
|
if (this.options.commandToExecute) {
|
||||||
if (this.currentExecution && this.options.restart) {
|
if (this.currentExecution && this.options.restart) {
|
||||||
logger.log('ok', `[${name}] restarting: ${this.options.commandToExecute}`);
|
logger.log('ok', `[${name}] restarting: ${this.options.commandToExecute}`);
|
||||||
this.currentExecution.kill();
|
await this.currentExecution.kill();
|
||||||
} else if (!this.currentExecution) {
|
} else if (!this.currentExecution) {
|
||||||
logger.log('ok', `[${name}] executing: ${this.options.commandToExecute}`);
|
logger.log('ok', `[${name}] executing: ${this.options.commandToExecute}`);
|
||||||
}
|
}
|
||||||
@@ -184,24 +184,32 @@ export class Watcher {
|
|||||||
* this method sets up a clean exit strategy
|
* this method sets up a clean exit strategy
|
||||||
*/
|
*/
|
||||||
private async setupCleanup() {
|
private async setupCleanup() {
|
||||||
|
// Last-resort synchronous cleanup — 'exit' event cannot await async work.
|
||||||
|
// By this point, SIGINT handler should have already called stop().
|
||||||
process.on('exit', () => {
|
process.on('exit', () => {
|
||||||
console.log('');
|
if (this.currentExecution && !this.currentExecution.childProcess.killed) {
|
||||||
console.log('now exiting!');
|
const pid = this.currentExecution.childProcess.pid;
|
||||||
this.stop();
|
if (pid) {
|
||||||
process.exit(0);
|
try {
|
||||||
|
process.kill(pid, 'SIGKILL');
|
||||||
|
} catch {
|
||||||
|
// Process may already be dead
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
process.on('SIGINT', () => {
|
process.on('SIGINT', async () => {
|
||||||
console.log('');
|
console.log('');
|
||||||
console.log('ok! got SIGINT We are exiting! Just cleaning up to exit neatly :)');
|
console.log('ok! got SIGINT We are exiting! Just cleaning up to exit neatly :)');
|
||||||
this.stop();
|
await this.stop();
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
// handle timeout
|
// handle timeout
|
||||||
if (this.options.timeout) {
|
if (this.options.timeout) {
|
||||||
plugins.smartdelay.delayFor(this.options.timeout).then(() => {
|
plugins.smartdelay.delayFor(this.options.timeout).then(async () => {
|
||||||
console.log(`timed out afer ${this.options.timeout} milliseconds! exiting!`);
|
console.log(`timed out afer ${this.options.timeout} milliseconds! exiting!`);
|
||||||
this.stop();
|
await this.stop();
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -216,7 +224,7 @@ export class Watcher {
|
|||||||
}
|
}
|
||||||
await this.smartwatchInstance.stop();
|
await this.smartwatchInstance.stop();
|
||||||
if (this.currentExecution && !this.currentExecution.childProcess.killed) {
|
if (this.currentExecution && !this.currentExecution.childProcess.killed) {
|
||||||
this.currentExecution.kill();
|
await this.currentExecution.kill();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user