mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2025-01-01 03:56:31 +00:00
51 lines
891 B
Go
51 lines
891 B
Go
//go:build unix
|
|
|
|
package dotlk
|
|
|
|
import (
|
|
"errors"
|
|
"io/fs"
|
|
"os"
|
|
"strconv"
|
|
|
|
"golang.org/x/sys/unix"
|
|
)
|
|
|
|
// TryLock returns nil if it acquired the lock,
|
|
// fs.ErrExist if another process has the lock.
|
|
func TryLock(name string) error {
|
|
for retry := true; retry; retry = false {
|
|
f, err := os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666)
|
|
if err == nil {
|
|
f.WriteString(strconv.Itoa(os.Getpid()))
|
|
f.Close()
|
|
return nil
|
|
}
|
|
if !errors.Is(err, fs.ErrExist) {
|
|
return err
|
|
}
|
|
if !removeStale(name) {
|
|
break
|
|
}
|
|
}
|
|
return fs.ErrExist
|
|
}
|
|
|
|
func removeStale(name string) bool {
|
|
buf, err := os.ReadFile(name)
|
|
if err != nil {
|
|
return errors.Is(err, fs.ErrNotExist)
|
|
}
|
|
|
|
pid, err := strconv.Atoi(string(buf))
|
|
if err != nil {
|
|
return false
|
|
}
|
|
if unix.Kill(pid, 0) == nil {
|
|
return false
|
|
}
|
|
|
|
err = os.Remove(name)
|
|
return err == nil || errors.Is(err, fs.ErrNotExist)
|
|
}
|