summaryrefslogtreecommitdiff
path: root/vendor/github.com/ncruces/go-sqlite3/internal/dotlk/dotlk_unix.go
blob: 177ab30bbdc965f330990de8c27771499584b49e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
//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)
}