@@ -858,16 +858,20 @@ class BackendManager {
858858 }
859859
860860 buildWindowsUnmanagedBackendMatcher ( backendConfig ) {
861- const expectedImageName = path . basename ( backendConfig . cmd || 'python.exe' ) . toLowerCase ( ) ;
861+ const safeBackendConfig =
862+ backendConfig && typeof backendConfig === 'object' ? backendConfig : { } ;
863+ const expectedImageName = path
864+ . basename ( safeBackendConfig . cmd || 'python.exe' )
865+ . toLowerCase ( ) ;
862866 const requireStrictCommandLineCheck =
863867 this . isGenericWindowsPythonImage ( expectedImageName ) ;
864868 const expectedCommandLineMarkers = [ ] ;
865- if ( Array . isArray ( backendConfig . args ) && backendConfig . args . length > 0 ) {
866- const primaryArg = backendConfig . args [ 0 ] ;
869+ if ( Array . isArray ( safeBackendConfig . args ) && safeBackendConfig . args . length > 0 ) {
870+ const primaryArg = safeBackendConfig . args [ 0 ] ;
867871 if ( typeof primaryArg === 'string' && primaryArg ) {
868872 const resolvedPrimaryArg = path . isAbsolute ( primaryArg )
869873 ? primaryArg
870- : path . resolve ( backendConfig . cwd || process . cwd ( ) , primaryArg ) ;
874+ : path . resolve ( safeBackendConfig . cwd || process . cwd ( ) , primaryArg ) ;
871875 expectedCommandLineMarkers . push (
872876 this . normalizeWindowsPathForMatch ( resolvedPrimaryArg ) ,
873877 ) ;
@@ -884,6 +888,18 @@ class BackendManager {
884888 } ;
885889 }
886890
891+ buildFallbackWindowsUnmanagedBackendMatcher ( ) {
892+ const fallbackCmdRaw = process . env . ASTRBOT_BACKEND_CMD || 'python.exe' ;
893+ const fallbackCmd = String ( fallbackCmdRaw ) . trim ( ) . split ( / \s + / , 1 ) [ 0 ] || 'python.exe' ;
894+ return {
895+ expectedImageName : path . basename ( fallbackCmd ) . toLowerCase ( ) ,
896+ // Fallback mode only checks image name to avoid false negatives
897+ // when backend config is unavailable in current session.
898+ requireStrictCommandLineCheck : false ,
899+ expectedCommandLineMarkers : [ ] ,
900+ } ;
901+ }
902+
887903 shouldKillUnmanagedBackendProcess ( pid , processInfo , processMatcher ) {
888904 const actualImageName = processInfo . imageName . toLowerCase ( ) ;
889905 if ( actualImageName !== processMatcher . expectedImageName ) {
@@ -944,8 +960,25 @@ class BackendManager {
944960 `Attempting unmanaged backend cleanup by port=${ port } pids=${ pids . join ( ',' ) } ` ,
945961 ) ;
946962
947- const backendConfig = this . getBackendConfig ( ) ;
948- const processMatcher = this . buildWindowsUnmanagedBackendMatcher ( backendConfig ) ;
963+ let backendConfig = null ;
964+ try {
965+ backendConfig = this . getBackendConfig ( ) ;
966+ } catch ( error ) {
967+ this . log (
968+ `Failed to resolve backend config during unmanaged cleanup: ${
969+ error instanceof Error ? error . message : String ( error )
970+ } `,
971+ ) ;
972+ }
973+ const hasBackendConfig = backendConfig && typeof backendConfig === 'object' ;
974+ const processMatcher = hasBackendConfig
975+ ? this . buildWindowsUnmanagedBackendMatcher ( backendConfig )
976+ : this . buildFallbackWindowsUnmanagedBackendMatcher ( ) ;
977+ if ( ! hasBackendConfig ) {
978+ this . log (
979+ 'Backend config is unavailable during unmanaged cleanup; falling back to image-name-only matching.' ,
980+ ) ;
981+ }
949982
950983 for ( const pid of pids ) {
951984 const processInfo = this . getWindowsProcessInfo ( pid ) ;
0 commit comments