11import { ChildProcess , fork } from 'node:child_process'
22import { join } from 'node:path'
33import { pathToFileURL } from 'node:url'
4+ import { clearTimeout } from 'node:timers'
45import semver from 'semver'
56import { clearFactory } from './clear.cjs'
67import { Options } from './cli.js'
@@ -23,7 +24,8 @@ export const dev = (script: string, scriptArgs: string[], nodeArgs: string[], {
2324 notify : notifyEnabled ,
2425 poll : forcePolling ,
2526 respawn,
26- timestamp
27+ timestamp,
28+ kill_timeout : killTimeout
2729} : Options ) => {
2830 if ( ! script ) {
2931 console . log ( 'Usage: node-dev [options] script [arguments]\n' )
@@ -55,6 +57,7 @@ export const dev = (script: string, scriptArgs: string[], nodeArgs: string[], {
5557
5658 const watcher = new FileWatcher ( { debounce, forcePolling, interval } )
5759 let isPaused = false
60+ let killTimer : NodeJS . Timeout | undefined
5861
5962 // The child_process
6063 let child : ( ChildProcess & { respawn ?: boolean } ) | undefined
@@ -87,6 +90,8 @@ export const dev = (script: string, scriptArgs: string[], nodeArgs: string[], {
8790 */
8891 function start ( ) {
8992 isPaused = false
93+ if ( killTimer )
94+ clearTimeout ( killTimer )
9095
9196 const args = nodeArgs . slice ( )
9297
@@ -128,6 +133,12 @@ export const dev = (script: string, scriptArgs: string[], nodeArgs: string[], {
128133 function stop ( willTerminate ?: boolean ) {
129134 child ! . respawn = true
130135 if ( ! willTerminate ) {
136+ if ( typeof killTimeout === 'number' ) {
137+ killTimer = setTimeout ( ( ) => {
138+ log . warn ( 'Sending SIGKILL after timeout (%s ms)' , killTimeout )
139+ child ?. kill ( 'SIGKILL' )
140+ } , killTimeout )
141+ }
131142 if ( gracefulIPC ) {
132143 log . info ( 'Sending IPC: ' + JSON . stringify ( gracefulIPC ) )
133144 child ! . send ( gracefulIPC )
0 commit comments