[优化] 确保所有管理的进程在停止时被正确取消和清理

This commit is contained in:
ryan
2026-06-02 21:30:48 +08:00
parent f29292dd81
commit dfd040a9de
4 changed files with 70 additions and 1 deletions
+1
View File
@@ -50,3 +50,4 @@ go.work.sum
*-source
*-source.*
.codex*
+1
View File
@@ -31,6 +31,7 @@ func (r *Runner) Run(ctx context.Context) error {
for {
select {
case <-ctx.Done():
r.FrpcManager.Stop()
return ctx.Err()
default:
}
+18 -1
View File
@@ -150,7 +150,10 @@ func (m *Manager) restartProcess(ctx context.Context, relayID string, configPath
_ = os.Remove(pidPath)
}
procCtx, cancel := context.WithCancel(context.Background())
if ctx == nil {
ctx = context.Background()
}
procCtx, cancel := context.WithCancel(ctx)
proc := &Process{
RelayID: relayID,
Cancel: cancel,
@@ -223,6 +226,20 @@ func (m *Manager) restartProcess(ctx context.Context, relayID string, configPath
}()
}
func (m *Manager) Stop() {
m.mu.Lock()
defer m.mu.Unlock()
for relayID, proc := range m.processes {
if proc != nil && proc.Cancel != nil {
proc.Cancel()
}
pidPath := filepath.Join(m.cfg.DataDir, fmt.Sprintf("frpc_%s.pid", relayID))
_ = os.Remove(pidPath)
delete(m.processes, relayID)
}
}
func buildFrpcToml(relay service.FlaredRelayInfo, proxies []service.FlaredProxyEntry) string {
var buf bytes.Buffer
+50
View File
@@ -335,3 +335,53 @@ func TestUpdateConfigKillsOrphanProcessBeforeRestart(t *testing.T) {
m.mu.RUnlock()
proc.Cancel()
}
func TestStopCancelsRunningProcesses(t *testing.T) {
scriptPath, dir := setupDummyScript(t)
writeControl(t, dir, 0, 30)
cfg := &config.Config{
ServerURL: "http://localhost:8080",
TunnelToken: "test-token",
FrpcPath: scriptPath,
DataDir: dir,
StatePath: filepath.Join(dir, "flared-state.json"),
}
m := NewManager(cfg)
newConfig := &service.FlaredTunnelConfigResponse{
Version: "1",
Checksum: "sum1",
Relays: []service.FlaredRelayInfo{
{
RelayNodeID: "relay-1",
Address: "127.0.0.1:7000",
AuthToken: "auth-1",
},
},
}
if err := m.UpdateConfig(context.Background(), newConfig); err != nil {
t.Fatalf("failed to UpdateConfig: %v", err)
}
assertStatusEventually(t, m, "relay-1", "running", 4*time.Second)
m.mu.RLock()
proc := m.processes["relay-1"]
if proc == nil || proc.Cmd == nil {
m.mu.RUnlock()
t.Fatal("expected running process to have a command handle")
}
cmd := proc.Cmd
m.mu.RUnlock()
m.Stop()
assertCommandExitedEventually(t, cmd, 2*time.Second)
m.mu.RLock()
defer m.mu.RUnlock()
if len(m.processes) != 0 {
t.Fatalf("expected no managed processes after stop, got %d", len(m.processes))
}
}