mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-08-11 01:03:51 +08:00
- 优先等待驱动代理自然退出,超时后再执行强制终止 - 进程已退出时忽略 Windows 终止权限竞态,避免连接成功被误判为失败 - 统一可选驱动与 MySQL agent 清理流程并补充回归测试
61 lines
1.1 KiB
Go
61 lines
1.1 KiB
Go
package db
|
|
|
|
import (
|
|
"errors"
|
|
"io"
|
|
"os/exec"
|
|
"time"
|
|
)
|
|
|
|
const agentProcessExitTimeout = 2 * time.Second
|
|
|
|
func closeAgentProcess(stdin io.Closer, cmd *exec.Cmd) error {
|
|
if stdin != nil {
|
|
_ = stdin.Close()
|
|
}
|
|
if cmd == nil || cmd.Process == nil {
|
|
return nil
|
|
}
|
|
return waitForAgentExit(cmd.Wait, cmd.Process.Kill, agentProcessExitTimeout)
|
|
}
|
|
|
|
func waitForAgentExit(wait func() error, kill func() error, timeout time.Duration) error {
|
|
if wait == nil {
|
|
return nil
|
|
}
|
|
if timeout <= 0 {
|
|
timeout = agentProcessExitTimeout
|
|
}
|
|
|
|
waitCh := make(chan error, 1)
|
|
go func() {
|
|
waitCh <- wait()
|
|
}()
|
|
|
|
timer := time.NewTimer(timeout)
|
|
defer timer.Stop()
|
|
select {
|
|
case <-waitCh:
|
|
return nil
|
|
case <-timer.C:
|
|
}
|
|
|
|
var killErr error
|
|
if kill != nil {
|
|
killErr = kill()
|
|
}
|
|
|
|
timer.Reset(timeout)
|
|
select {
|
|
case <-waitCh:
|
|
// The process is already reaped. A concurrent Kill can report access
|
|
// denied on Windows even though cleanup completed successfully.
|
|
return nil
|
|
case <-timer.C:
|
|
if killErr != nil {
|
|
return killErr
|
|
}
|
|
return errors.New("driver agent process did not exit after termination")
|
|
}
|
|
}
|