Files
frpc-console/process_manager_lock_linux.go
T

66 lines
1.2 KiB
Go

//go:build linux
package main
import (
"fmt"
"os"
"path/filepath"
"time"
"golang.org/x/sys/unix"
)
func (pm *ProcessManager) Lock() error {
pm.mu.Lock()
defer pm.mu.Unlock()
if pm.locked {
return nil
}
lockPath := filepath.Join(pm.dataDir, LockFileName)
if err := os.MkdirAll(pm.dataDir, 0755); err != nil {
return fmt.Errorf("创建数据目录失败: %w", err)
}
file, err := os.OpenFile(lockPath, os.O_CREATE|os.O_RDWR, 0644)
if err != nil {
return fmt.Errorf("打开锁文件失败: %w", err)
}
start := time.Now()
for {
err := unix.Flock(int(file.Fd()), unix.LOCK_EX|unix.LOCK_NB)
if err == nil {
pm.lockFile = file
pm.locked = true
return nil
}
if err != unix.EWOULDBLOCK {
file.Close()
return fmt.Errorf("获取锁失败: %w", err)
}
if time.Since(start) > LockAcquireTimeout {
file.Close()
return fmt.Errorf("获取锁超时 (超过 %v)", LockAcquireTimeout)
}
time.Sleep(LockRetryInterval)
}
}
func (pm *ProcessManager) Unlock() error {
pm.mu.Lock()
defer pm.mu.Unlock()
if !pm.locked {
return nil
}
if pm.lockFile != nil {
unix.Flock(int(pm.lockFile.Fd()), unix.LOCK_UN)
pm.lockFile.Close()
pm.lockFile = nil
}
pm.locked = false
return nil
}