...
Source file src/cmd/go/internal/lockedfile/lockedfile_plan9.go
1
2
3
4
5
6
7 package lockedfile
8
9 import (
10 "math/rand"
11 "os"
12 "strings"
13 "time"
14 )
15
16
17
18
19
20
21
22 var lockedErrStrings = [...]string{
23 "file is locked",
24 "exclusive lock",
25 "exclusive use file already open",
26 }
27
28
29
30
31
32 func isLocked(err error) bool {
33 s := err.Error()
34
35 for _, frag := range lockedErrStrings {
36 if strings.Contains(s, frag) {
37 return true
38 }
39 }
40
41 return false
42 }
43
44 func openFile(name string, flag int, perm os.FileMode) (*os.File, error) {
45
46
47
48
49
50
51
52
53
54
55
56
57
58 if fi, err := os.Stat(name); err == nil {
59 if fi.Mode()&os.ModeExclusive == 0 {
60 if err := os.Chmod(name, fi.Mode()|os.ModeExclusive); err != nil {
61 return nil, err
62 }
63 }
64 } else if !os.IsNotExist(err) {
65 return nil, err
66 }
67
68 nextSleep := 1 * time.Millisecond
69 const maxSleep = 500 * time.Millisecond
70 for {
71 f, err := os.OpenFile(name, flag, perm|os.ModeExclusive)
72 if err == nil {
73 return f, nil
74 }
75
76 if !isLocked(err) {
77 return nil, err
78 }
79
80 time.Sleep(nextSleep)
81
82 nextSleep += nextSleep
83 if nextSleep > maxSleep {
84 nextSleep = maxSleep
85 }
86
87 nextSleep += time.Duration((0.1*rand.Float64() - 0.05) * float64(nextSleep))
88 }
89 }
90
91 func closeFile(f *os.File) error {
92 return f.Close()
93 }
94
View as plain text