68 lines
1.3 KiB
Go
68 lines
1.3 KiB
Go
//go:build linux
|
|
|
|
package process
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"time"
|
|
|
|
"golang.org/x/sys/unix"
|
|
)
|
|
|
|
// Lock 获取进程间互斥锁 (Linux: flock)
|
|
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)
|
|
}
|
|
}
|
|
|
|
// Unlock 释放互斥锁 (Linux: flock)
|
|
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
|
|
}
|