package backend import ( "ant-chrome/backend/internal/logger" "fmt" "time" "github.com/wailsapp/wails/v2/pkg/runtime" ) func (a *App) waitBrowserProcess(profileId string, monitor *browserProcessMonitor) { err := monitor.Wait() log := logger.New("Browser") debugPort := 0 profileName := profileId shouldMonitorDetached := false a.browserMgr.Mutex.Lock() profile, exists := a.browserMgr.Profiles[profileId] wasRunning := exists && profile.Running if exists { profileName = profile.ProfileName debugPort = profile.DebugPort } a.browserMgr.Mutex.Unlock() if wasRunning && debugPort > 0 { snapshot, changed := a.waitForBrowserDebugReady(profileId, debugPort, browserLauncherDetachGraceWindow) if warningSnapshot, warningChanged := a.finalizeDeferredStartTargets(profileId, debugPort); warningSnapshot != nil { snapshot = warningSnapshot changed = changed || warningChanged } if snapshot != nil && changed { log.Info("浏览器启动器进程退出后,调试接口延迟就绪", logger.F("profile_id", profileId), logger.F("debug_port", debugPort), ) a.emitBrowserInstanceUpdated(snapshot) } a.browserMgr.Mutex.Lock() profile, exists = a.browserMgr.Profiles[profileId] if exists && profile.Running && profile.DebugPort == debugPort && profile.DebugReady && canConnectDebugPort(debugPort, 250*time.Millisecond) { delete(a.browserMgr.BrowserProcesses, profileId) profile.Pid = 0 shouldMonitorDetached = true } a.browserMgr.Mutex.Unlock() if shouldMonitorDetached { log.Info("浏览器启动器进程已退出,切换为调试端口存活监控", logger.F("profile_id", profileId), logger.F("profile_name", profileName), logger.F("debug_port", debugPort), ) a.waitDetachedBrowser(profileId, debugPort) return } } a.browserMgr.Mutex.Lock() profile, exists = a.browserMgr.Profiles[profileId] wasRunning = exists && profile.Running if exists { profileName = profile.ProfileName a.markProfileStoppedLocked(profileId, profile) } a.browserMgr.Mutex.Unlock() if a.ctx == nil { return } if wasRunning && err != nil { if exists && profile != nil { profile.LastError = fmt.Sprintf("实例运行异常退出:%s", err.Error()) } log.Error("浏览器进程异常退出", logger.F("profile_id", profileId), logger.F("profile_name", profileName), logger.F("error", err)) runtime.EventsEmit(a.ctx, "browser:instance:crashed", map[string]interface{}{ "profileId": profileId, "profileName": profileName, "error": err.Error(), }) } else { runtime.EventsEmit(a.ctx, "browser:instance:stopped", profileId) } } func (a *App) waitDetachedBrowser(profileId string, debugPort int) { const ( pollInterval = 500 * time.Millisecond maxMisses = 3 ) log := logger.New("Browser") misses := 0 for { if canConnectDebugPort(debugPort, 250*time.Millisecond) { misses = 0 time.Sleep(pollInterval) continue } misses++ if misses < maxMisses { time.Sleep(pollInterval) continue } profileName := profileId a.browserMgr.Mutex.Lock() profile, exists := a.browserMgr.Profiles[profileId] if !exists || !profile.Running || profile.DebugPort != debugPort { a.browserMgr.Mutex.Unlock() return } profileName = profile.ProfileName a.markProfileStoppedLocked(profileId, profile) a.browserMgr.Mutex.Unlock() log.Info("检测到浏览器调试端口关闭,实例已停止", logger.F("profile_id", profileId), logger.F("profile_name", profileName), logger.F("debug_port", debugPort), ) if a.ctx != nil { runtime.EventsEmit(a.ctx, "browser:instance:stopped", profileId) } return } }