refactor(watchdog): remove tcp socket connection and add local unix sock connection

This commit is contained in:
2026-05-10 14:38:52 +08:00
parent 9c684241d1
commit ef27e7e0a9
10 changed files with 86 additions and 82 deletions

View File

@@ -65,7 +65,6 @@ func LoadConfig(configPath string, getInitSystem func() string) error {
global.CurrentConfig.InstancePath = fileConfig.InstancePath
global.CurrentConfig.Debug = fileConfig.Debug
global.CurrentConfig.Watchdog.Enabled = fileConfig.Watchdog.Enabled
global.CurrentConfig.Watchdog.Port = fileConfig.Watchdog.Port
global.CurrentConfig.Notification.Enabled = fileConfig.Notification.Enabled
global.CurrentConfig.Notification.Method = fileConfig.Notification.Method
global.CurrentConfig.Webhook.Method = fileConfig.Webhook.Method
@@ -93,10 +92,6 @@ func LoadConfig(configPath string, getInitSystem func() string) error {
global.CurrentConfig.InstancePath = "./configs"
}
if fileConfig.Watchdog.Port == 0 {
global.CurrentConfig.Watchdog.Port = 12380
}
if err := os.MkdirAll(global.CurrentConfig.InstancePath, 0755); err != nil {
return fmt.Errorf("failed to create config directory: %w", err)
}

View File

@@ -1655,7 +1655,6 @@ key=ListenAddr
"InstancePath": "./configs",
"Debug": true,
"Watchdog.Enabled": true,
"Watchdog.Port": 12380,
"Notification.Enabled": true,
"Notification.Method": "webhook",
"Webhook.Method": "POST",

View File

@@ -51,7 +51,6 @@ type Config struct {
Debug bool `json:"debug"`
Watchdog struct {
Enabled bool `json:"enabled"`
Port int `json:"port"`
} `json:"watchdog"`
Notification struct {
Enabled bool `json:"enabled"`
@@ -73,10 +72,8 @@ var CurrentConfig = Config{
Debug: false,
Watchdog: struct {
Enabled bool `json:"enabled"`
Port int `json:"port"`
}{
Enabled: false,
Port: 0,
},
Notification: struct {
Enabled bool `json:"enabled"`

View File

@@ -37,8 +37,6 @@ func GetSettingsHandler(w http.ResponseWriter, r *http.Request) {
value = global.CurrentConfig.Debug
case "Watchdog.Enabled":
value = global.CurrentConfig.Watchdog.Enabled
case "Watchdog.Port":
value = global.CurrentConfig.Watchdog.Port
case "Notification.Enabled":
value = global.CurrentConfig.Notification.Enabled
case "Notification.Method":
@@ -68,7 +66,6 @@ func GetSettingsHandler(w http.ResponseWriter, r *http.Request) {
"InstancePath": global.CurrentConfig.InstancePath,
"Debug": global.CurrentConfig.Debug,
"Watchdog.Enabled": global.CurrentConfig.Watchdog.Enabled,
"Watchdog.Port": global.CurrentConfig.Watchdog.Port,
"Notification.Enabled": global.CurrentConfig.Notification.Enabled,
"Notification.Method": global.CurrentConfig.Notification.Method,
"Webhook.Method": global.CurrentConfig.Webhook.Method,
@@ -131,10 +128,6 @@ func SetSettingsHandler(w http.ResponseWriter, r *http.Request) {
if v, ok := value.(bool); ok {
global.CurrentConfig.Watchdog.Enabled = v
}
case "Watchdog.Port":
if v, ok := value.(float64); ok {
global.CurrentConfig.Watchdog.Port = int(v)
}
case "Notification.Enabled":
if v, ok := value.(bool); ok {
global.CurrentConfig.Notification.Enabled = v

View File

@@ -76,11 +76,10 @@ func main() {
if err != nil {
postLog.Error(fmt.Sprintf("Unable to initialize Watchdog: %s", err))
} else {
if !watchdog.Connect("127.0.0.1", global.CurrentConfig.Watchdog.Port) {
postLog.Error(fmt.Sprintf("Failed to connect to Watchdog at %s:%d", "127.0.0.1", global.CurrentConfig.Watchdog.Port))
if !watchdog.Connect() {
postLog.Error("Failed to connect to Watchdog")
} else {
postLog.Info(fmt.Sprintf("Connected to Watchdog at %s:%d", "127.0.0.1", global.CurrentConfig.Watchdog.Port))
global.Is.WatchdogConnected = true
postLog.Info("Connected to Watchdog successfully")
go func() {
if err := watchdog.StartKeepAlive(); err != nil {

View File

@@ -16,9 +16,11 @@ import (
"time"
)
const socketPath = "/tmp/super-frpc-watchdog.sock"
var (
tcpConn net.Conn
tcpConnMutex sync.Mutex
localConn net.Conn
localConnMutex sync.Mutex
isConnected bool
recvChan chan string
stopRecvChan chan struct{}
@@ -26,16 +28,16 @@ var (
)
func Init() error {
tcpConnMutex.Lock()
localConnMutex.Lock()
if recvChan != nil || stopRecvChan != nil {
tcpConnMutex.Unlock()
localConnMutex.Unlock()
return nil
}
if tcpConn != nil {
tcpConnMutex.Unlock()
return fmt.Errorf("TCP client already initialized")
if localConn != nil {
localConnMutex.Unlock()
return fmt.Errorf("local socket client already initialized")
}
tcpConnMutex.Unlock()
localConnMutex.Unlock()
if global.CurrentConfig.Watchdog.Enabled {
if err := ensureWatchdogProcess(); err != nil {
@@ -44,8 +46,8 @@ func Init() error {
}
}
tcpConnMutex.Lock()
defer tcpConnMutex.Unlock()
localConnMutex.Lock()
defer localConnMutex.Unlock()
recvChan = make(chan string, 100)
stopRecvChan = make(chan struct{})
@@ -135,21 +137,20 @@ func isWatchdogProcessRunning(watchdogName string) bool {
}
}
func tcpConnect(ipaddr string, port int) error {
tcpConnMutex.Lock()
defer tcpConnMutex.Unlock()
func localSocketConnect() error {
localConnMutex.Lock()
defer localConnMutex.Unlock()
if tcpConn != nil {
if localConn != nil {
return fmt.Errorf("already connected")
}
address := net.JoinHostPort(ipaddr, fmt.Sprintf("%d", port))
conn, err := net.DialTimeout("tcp", address, 3*time.Second)
conn, err := net.DialTimeout("unix", socketPath, 3*time.Second)
if err != nil {
return fmt.Errorf("failed to connect to %s: %v", address, err)
return fmt.Errorf("failed to connect to %s: %v", socketPath, err)
}
tcpConn = conn
localConn = conn
isConnected = true
recvWg.Add(1)
@@ -159,20 +160,20 @@ func tcpConnect(ipaddr string, port int) error {
}
func sendMsg(message string, timeout int) (string, error) {
tcpConnMutex.Lock()
localConnMutex.Lock()
if tcpConn == nil {
tcpConnMutex.Unlock()
if localConn == nil {
localConnMutex.Unlock()
return "", fmt.Errorf("not connected")
}
_, err := tcpConn.Write([]byte(message + "\n"))
_, err := localConn.Write([]byte(message + "\n"))
if err != nil {
tcpConnMutex.Unlock()
localConnMutex.Unlock()
return "", fmt.Errorf("failed to send message: %v", err)
}
tcpConnMutex.Unlock()
localConnMutex.Unlock()
select {
case response := <-recvChan:
@@ -188,13 +189,13 @@ func sendMsg(message string, timeout int) (string, error) {
func recvMsg() {
defer recvWg.Done()
tcpConnMutex.Lock()
if tcpConn == nil {
tcpConnMutex.Unlock()
localConnMutex.Lock()
if localConn == nil {
localConnMutex.Unlock()
return
}
conn := tcpConn
tcpConnMutex.Unlock()
conn := localConn
localConnMutex.Unlock()
reader := bufio.NewReader(conn)
@@ -215,9 +216,7 @@ func recvMsg() {
default:
// drop the message
}
// Here add logic to handle the message
if !isResponseMessage(line) {
// postLog.Debug(fmt.Sprintf("[Watchdog] TCP Socket received message: %s", line))
parseCommand(line)
}
}
@@ -228,13 +227,13 @@ func recvMsg() {
continue
}
tcpConnMutex.Lock()
if tcpConn != nil {
tcpConn.Close()
tcpConn = nil
localConnMutex.Lock()
if localConn != nil {
localConn.Close()
localConn = nil
isConnected = false
}
tcpConnMutex.Unlock()
localConnMutex.Unlock()
return
}
}
@@ -246,23 +245,23 @@ func isResponseMessage(msg string) bool {
}
func Destroy() error {
tcpConnMutex.Lock()
localConnMutex.Lock()
if stopRecvChan != nil {
close(stopRecvChan)
stopRecvChan = nil
}
tcpConnMutex.Unlock()
localConnMutex.Unlock()
recvWg.Wait()
tcpConnMutex.Lock()
defer tcpConnMutex.Unlock()
localConnMutex.Lock()
defer localConnMutex.Unlock()
if tcpConn != nil {
err := tcpConn.Close()
tcpConn = nil
if localConn != nil {
err := localConn.Close()
localConn = nil
isConnected = false
if err != nil {
return fmt.Errorf("failed to close connection: %v", err)
@@ -278,7 +277,7 @@ func Destroy() error {
}
func IsConnected() bool {
tcpConnMutex.Lock()
defer tcpConnMutex.Unlock()
return isConnected && tcpConn != nil
localConnMutex.Lock()
defer localConnMutex.Unlock()
return isConnected && localConn != nil
}

View File

@@ -6,7 +6,7 @@ import (
"time"
)
func Connect(ipaddr string, port int) bool {
func Connect() bool {
if IsConnected() {
return true
}
@@ -18,7 +18,7 @@ func Connect(ipaddr string, port int) bool {
deadline := time.Now().Add(5 * time.Second)
var lastErr error
for {
if err := tcpConnect(ipaddr, port); err == nil {
if err := localSocketConnect(); err == nil {
break
} else {
lastErr = err
@@ -58,6 +58,8 @@ func Disconnect() bool {
return false
}
KillWatchdogProcess()
time.Sleep(100 * time.Millisecond)
return true

View File

@@ -29,7 +29,7 @@ func StartKeepAlive() error {
continue
}
if Connect("127.0.0.1", global.CurrentConfig.Watchdog.Port) {
if err = Init(); err == nil && Connect() {
global.Is.WatchdogConnected = true
postLog.Info("[watchdog] successfully reconnected to watchdog")
lastErr = nil
@@ -37,7 +37,7 @@ func StartKeepAlive() error {
}
lastErr = fmt.Errorf("failed to connect to watchdog")
time.Sleep(500 * time.Millisecond)
time.Sleep(1000 * time.Millisecond)
}
if lastErr != nil {

View File

@@ -6,3 +6,13 @@ import "os/exec"
func configureWatchdogCommand(cmd *exec.Cmd) {
}
func KillWatchdogProcess() error {
watchdogName, err := getWatchdogBinaryName()
if err != nil {
return err
}
cmd := exec.Command("pkill", "-f", watchdogName)
return cmd.Run()
}

View File

@@ -10,3 +10,13 @@ import (
func configureWatchdogCommand(cmd *exec.Cmd) {
cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}
}
func KillWatchdogProcess() error {
watchdogName, err := getWatchdogBinaryName()
if err != nil {
return err
}
cmd := exec.Command("taskkill", "/IM", watchdogName, "/F")
return cmd.Run()
}