@@ -463,6 +463,24 @@ async function waitForGatewayPortRelease(port: number, timeoutMs = 5_000): Promi
463463 return false ;
464464}
465465
466+ async function terminateBusyPortListeners ( port : number ) : Promise < number [ ] > {
467+ const diagnostics = await inspectPortUsage ( port ) . catch ( ( ) => null ) ;
468+ if ( diagnostics ?. status !== "busy" ) {
469+ return [ ] ;
470+ }
471+ const pids = Array . from (
472+ new Set (
473+ diagnostics . listeners
474+ . map ( ( listener ) => listener . pid )
475+ . filter ( ( pid ) : pid is number => Number . isFinite ( pid ) && pid > 0 ) ,
476+ ) ,
477+ ) ;
478+ for ( const pid of pids ) {
479+ await terminateGatewayProcessTree ( pid , 300 ) ;
480+ }
481+ return pids ;
482+ }
483+
466484async function resolveFallbackRuntime ( env : GatewayServiceEnv ) : Promise < GatewayServiceRuntime > {
467485 const port = resolveConfiguredGatewayPort ( env ) ;
468486 if ( ! port ) {
@@ -655,7 +673,14 @@ export async function stopScheduledTask({ stdout, env }: GatewayServiceControlAr
655673 await terminateScheduledTaskGatewayListeners ( effectiveEnv ) ;
656674 await terminateInstalledStartupRuntime ( effectiveEnv ) ;
657675 if ( stopPort ) {
658- await waitForGatewayPortRelease ( stopPort ) ;
676+ const released = await waitForGatewayPortRelease ( stopPort ) ;
677+ if ( ! released ) {
678+ await terminateBusyPortListeners ( stopPort ) ;
679+ const releasedAfterForce = await waitForGatewayPortRelease ( stopPort , 2_000 ) ;
680+ if ( ! releasedAfterForce ) {
681+ throw new Error ( `gateway port ${ stopPort } is still busy after stop` ) ;
682+ }
683+ }
659684 }
660685 stdout . write ( `${ formatLine ( "Stopped Scheduled Task" , taskName ) } \n` ) ;
661686}
@@ -684,7 +709,14 @@ export async function restartScheduledTask({
684709 await terminateScheduledTaskGatewayListeners ( effectiveEnv ) ;
685710 await terminateInstalledStartupRuntime ( effectiveEnv ) ;
686711 if ( restartPort ) {
687- await waitForGatewayPortRelease ( restartPort ) ;
712+ const released = await waitForGatewayPortRelease ( restartPort ) ;
713+ if ( ! released ) {
714+ await terminateBusyPortListeners ( restartPort ) ;
715+ const releasedAfterForce = await waitForGatewayPortRelease ( restartPort , 2_000 ) ;
716+ if ( ! releasedAfterForce ) {
717+ throw new Error ( `gateway port ${ restartPort } is still busy before restart` ) ;
718+ }
719+ }
688720 }
689721 const res = await execSchtasks ( [ "/Run" , "/TN" , taskName ] ) ;
690722 if ( res . code !== 0 ) {
0 commit comments