@@ -34,6 +34,13 @@ const (
34
34
writeLock lockType = unix .F_WRLCK
35
35
)
36
36
37
+ type cmdType int
38
+
39
+ const (
40
+ tryLock cmdType = unix .F_SETLK
41
+ waitLock cmdType = unix .F_SETLKW
42
+ )
43
+
37
44
type inode = uint64
38
45
39
46
type inodeLock struct {
@@ -90,15 +97,15 @@ func (f *Flock) lock(locked *bool, flag lockType) error {
90
97
defer f .ensureFhState ()
91
98
}
92
99
93
- if _ , err := f .doLock (flag , true ); err != nil {
100
+ if _ , err := f .doLock (waitLock , flag , true ); err != nil {
94
101
return err
95
102
}
96
103
97
104
* locked = true
98
105
return nil
99
106
}
100
107
101
- func (f * Flock ) doLock (lt lockType , blocking bool ) (bool , error ) {
108
+ func (f * Flock ) doLock (cmd cmdType , lt lockType , blocking bool ) (bool , error ) {
102
109
// POSIX locks apply per inode and process, and the lock for an inode is
103
110
// released when *any* descriptor for that inode is closed. So we need to
104
111
// synchronize access to each inode internally, and must serialize lock and
@@ -143,10 +150,13 @@ func (f *Flock) doLock(lt lockType, blocking bool) (bool, error) {
143
150
wait <- f
144
151
}
145
152
146
- err = setlkw (f .fh .Fd (), lt )
153
+ err = setlkw (f .fh .Fd (), cmd , lt )
147
154
148
155
if err != nil {
149
156
f .doUnlock ()
157
+ if cmd == tryLock && err == unix .EACCES {
158
+ return false , nil
159
+ }
150
160
return false , err
151
161
}
152
162
@@ -186,7 +196,7 @@ func (f *Flock) doUnlock() (err error) {
186
196
mu .Unlock ()
187
197
188
198
if owner == f {
189
- err = setlkw (f .fh .Fd (), unix .F_UNLCK )
199
+ err = setlkw (f .fh .Fd (), waitLock , unix .F_UNLCK )
190
200
}
191
201
192
202
mu .Lock ()
@@ -246,7 +256,7 @@ func (f *Flock) try(locked *bool, flag lockType) (bool, error) {
246
256
defer f .ensureFhState ()
247
257
}
248
258
249
- haslock , err := f .doLock (flag , false )
259
+ haslock , err := f .doLock (tryLock , flag , false )
250
260
if err != nil {
251
261
return false , err
252
262
}
@@ -255,10 +265,10 @@ func (f *Flock) try(locked *bool, flag lockType) (bool, error) {
255
265
return haslock , nil
256
266
}
257
267
258
- // setlkw calls FcntlFlock with F_SETLKW for the entire file indicated by fd.
259
- func setlkw (fd uintptr , lt lockType ) error {
268
+ // setlkw calls FcntlFlock with cmd for the entire file indicated by fd.
269
+ func setlkw (fd uintptr , cmd cmdType , lt lockType ) error {
260
270
for {
261
- err := unix .FcntlFlock (fd , unix . F_SETLKW , & unix.Flock_t {
271
+ err := unix .FcntlFlock (fd , int ( cmd ) , & unix.Flock_t {
262
272
Type : int16 (lt ),
263
273
Whence : io .SeekStart ,
264
274
Start : 0 ,
0 commit comments