Update upstream source from tag 'upstream/1.2.0'
Update to upstream version '1.2.0'
with Debian dir cb5a13b3b66ca0a6d7032b58044a164d478cef97
Shengjing Zhu
1 year, 8 months ago
0 | name: Go | |
1 | ||
2 | on: | |
3 | push: | |
4 | branches: [ master ] | |
5 | pull_request: | |
6 | branches: [ master ] | |
7 | ||
8 | jobs: | |
9 | ||
10 | # Unfortunately there is much duplication below. I have not found a | |
11 | # way to set "runs-on" to an array, so instead I duplicated the | |
12 | # whole thing three times. | |
13 | ||
14 | linux_build_and_test: | |
15 | name: Build and test (Linux) | |
16 | runs-on: windows-latest | |
17 | strategy: | |
18 | fail-fast: false | |
19 | matrix: | |
20 | go: ['1.13', '1.14', '1.15', '1.16'] | |
21 | steps: | |
22 | - id: go | |
23 | name: Set up Go | |
24 | uses: actions/setup-go@v1 | |
25 | with: | |
26 | go-version: ${{ matrix.go }} | |
27 | - name: Checkout | |
28 | uses: actions/checkout@v2 | |
29 | - name: Build | |
30 | run: go build -v . | |
31 | - name: Test | |
32 | run: go test -v . | |
33 | ||
34 | windows_build_and_test: | |
35 | name: Build and test (Windows) | |
36 | runs-on: windows-latest | |
37 | strategy: | |
38 | fail-fast: false | |
39 | matrix: | |
40 | go: ['1.13', '1.14', '1.15', '1.16'] | |
41 | steps: | |
42 | - id: go | |
43 | name: Set up Go | |
44 | uses: actions/setup-go@v1 | |
45 | with: | |
46 | go-version: ${{ matrix.go }} | |
47 | - name: Checkout | |
48 | uses: actions/checkout@v2 | |
49 | - name: Build | |
50 | run: go build -v . | |
51 | - name: Test | |
52 | run: go test -v . | |
53 | ||
54 | macos_build_and_test: | |
55 | name: Build and test (macOS) | |
56 | runs-on: macos-latest | |
57 | strategy: | |
58 | fail-fast: false | |
59 | matrix: | |
60 | go: ['1.13', '1.14', '1.15', '1.16'] | |
61 | steps: | |
62 | - id: go | |
63 | name: Set up Go | |
64 | uses: actions/setup-go@v1 | |
65 | with: | |
66 | go-version: ${{ matrix.go }} | |
67 | - name: Checkout | |
68 | uses: actions/checkout@v2 | |
69 | - name: Build | |
70 | run: go build -v . | |
71 | - name: Test | |
72 | run: go test -v . |
1 | 1 | // Use of this source code is governed by a BSD-style |
2 | 2 | // license that can be found in the LICENSE file. |
3 | 3 | |
4 | // +build darwin dragonfly freebsd linux netbsd openbsd | |
4 | // +build darwin dragonfly freebsd linux netbsd openbsd solaris | |
5 | 5 | |
6 | 6 | package filemutex |
7 | 7 | |
8 | import ( | |
9 | "syscall" | |
10 | ) | |
8 | import "golang.org/x/sys/unix" | |
11 | 9 | |
12 | 10 | const ( |
13 | 11 | mkdirPerm = 0750 |
20 | 18 | } |
21 | 19 | |
22 | 20 | func New(filename string) (*FileMutex, error) { |
23 | fd, err := syscall.Open(filename, syscall.O_CREAT|syscall.O_RDONLY, mkdirPerm) | |
21 | fd, err := unix.Open(filename, unix.O_CREAT|unix.O_RDONLY, mkdirPerm) | |
24 | 22 | if err != nil { |
25 | 23 | return nil, err |
26 | 24 | } |
28 | 26 | } |
29 | 27 | |
30 | 28 | func (m *FileMutex) Lock() error { |
31 | if err := syscall.Flock(m.fd, syscall.LOCK_EX); err != nil { | |
32 | return err | |
33 | } | |
34 | return nil | |
29 | return unix.Flock(m.fd, unix.LOCK_EX) | |
35 | 30 | } |
36 | 31 | |
37 | 32 | func (m *FileMutex) TryLock() error { |
38 | if err := syscall.Flock(m.fd, syscall.LOCK_EX|syscall.LOCK_NB); err != nil { | |
39 | if errno, ok := err.(syscall.Errno); ok { | |
40 | if errno == syscall.EWOULDBLOCK { | |
33 | if err := unix.Flock(m.fd, unix.LOCK_EX|unix.LOCK_NB); err != nil { | |
34 | if errno, ok := err.(unix.Errno); ok { | |
35 | if errno == unix.EWOULDBLOCK { | |
41 | 36 | return AlreadyLocked |
42 | 37 | } |
43 | 38 | } |
47 | 42 | } |
48 | 43 | |
49 | 44 | func (m *FileMutex) Unlock() error { |
50 | if err := syscall.Flock(m.fd, syscall.LOCK_UN); err != nil { | |
51 | return err | |
52 | } | |
53 | return nil | |
45 | return unix.Flock(m.fd, unix.LOCK_UN) | |
54 | 46 | } |
55 | 47 | |
56 | 48 | func (m *FileMutex) RLock() error { |
57 | if err := syscall.Flock(m.fd, syscall.LOCK_SH); err != nil { | |
58 | return err | |
59 | } | |
60 | return nil | |
49 | return unix.Flock(m.fd, unix.LOCK_SH) | |
61 | 50 | } |
62 | 51 | |
63 | 52 | func (m *FileMutex) RUnlock() error { |
64 | if err := syscall.Flock(m.fd, syscall.LOCK_UN); err != nil { | |
65 | return err | |
66 | } | |
67 | return nil | |
53 | return unix.Flock(m.fd, unix.LOCK_UN) | |
68 | 54 | } |
69 | 55 | |
70 | 56 | // Close unlocks the lock and closes the underlying file descriptor. |
71 | 57 | func (m *FileMutex) Close() error { |
72 | if err := syscall.Flock(m.fd, syscall.LOCK_UN); err != nil { | |
58 | if err := unix.Flock(m.fd, unix.LOCK_UN); err != nil { | |
73 | 59 | return err |
74 | 60 | } |
75 | return syscall.Close(m.fd) | |
61 | return unix.Close(m.fd) | |
76 | 62 | } |
72 | 72 | m.Close() |
73 | 73 | } |
74 | 74 | |
75 | func TestOnlyClose(t *testing.T) { | |
76 | dir, err := ioutil.TempDir("", "") | |
77 | require.NoError(t, err) | |
78 | defer os.RemoveAll(dir) | |
79 | ||
80 | path := filepath.Join(dir, "x") | |
81 | m, err := New(path) | |
82 | require.NoError(t, err) | |
83 | ||
84 | require.NoError(t, m.Close()) | |
85 | } | |
86 | ||
75 | 87 | func TestLockErrorsAreRecoverable(t *testing.T) { |
76 | 88 | dir, err := ioutil.TempDir("", "") |
77 | 89 | require.NoError(t, err) |
5 | 5 | |
6 | 6 | import ( |
7 | 7 | "syscall" |
8 | "unsafe" | |
8 | ||
9 | "golang.org/x/sys/windows" | |
9 | 10 | ) |
10 | 11 | |
11 | var ( | |
12 | modkernel32 = syscall.NewLazyDLL("kernel32.dll") | |
13 | procLockFileEx = modkernel32.NewProc("LockFileEx") | |
14 | procUnlockFileEx = modkernel32.NewProc("UnlockFileEx") | |
15 | ) | |
16 | ||
17 | const ( | |
18 | lockfileFailImmediately = 1 | |
19 | lockfileExclusiveLock = 2 | |
20 | ) | |
21 | ||
22 | func lockFileEx(h syscall.Handle, flags, reserved, locklow, lockhigh uint32, ol *syscall.Overlapped) (err error) { | |
23 | r1, _, e1 := syscall.Syscall6(procLockFileEx.Addr(), 6, uintptr(h), uintptr(flags), uintptr(reserved), uintptr(locklow), uintptr(lockhigh), uintptr(unsafe.Pointer(ol))) | |
24 | if r1 == 0 { | |
25 | if e1 != 0 { | |
26 | err = error(e1) | |
27 | } else { | |
28 | err = syscall.EINVAL | |
29 | } | |
30 | } | |
31 | return | |
32 | } | |
33 | ||
34 | func unlockFileEx(h syscall.Handle, reserved, locklow, lockhigh uint32, ol *syscall.Overlapped) (err error) { | |
35 | r1, _, e1 := syscall.Syscall6(procUnlockFileEx.Addr(), 5, uintptr(h), uintptr(reserved), uintptr(locklow), uintptr(lockhigh), uintptr(unsafe.Pointer(ol)), 0) | |
36 | if r1 == 0 { | |
37 | if e1 != 0 { | |
38 | err = error(e1) | |
39 | } else { | |
40 | err = syscall.EINVAL | |
41 | } | |
42 | } | |
43 | return | |
44 | } | |
12 | // see https://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs.85).aspx | |
13 | var errLockUnlocked syscall.Errno = 0x9E | |
45 | 14 | |
46 | 15 | // FileMutex is similar to sync.RWMutex, but also synchronizes across processes. |
47 | 16 | // This implementation is based on flock syscall. |
48 | 17 | type FileMutex struct { |
49 | fd syscall.Handle | |
18 | fd windows.Handle | |
50 | 19 | } |
51 | 20 | |
52 | 21 | func New(filename string) (*FileMutex, error) { |
53 | fd, err := syscall.CreateFile(&(syscall.StringToUTF16(filename)[0]), syscall.GENERIC_READ|syscall.GENERIC_WRITE, | |
54 | syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE, nil, syscall.OPEN_ALWAYS, syscall.FILE_ATTRIBUTE_NORMAL, 0) | |
22 | fd, err := windows.CreateFile(&(windows.StringToUTF16(filename)[0]), windows.GENERIC_READ|windows.GENERIC_WRITE, | |
23 | windows.FILE_SHARE_READ|windows.FILE_SHARE_WRITE, nil, windows.OPEN_ALWAYS, windows.FILE_ATTRIBUTE_NORMAL, 0) | |
55 | 24 | if err != nil { |
56 | 25 | return nil, err |
57 | 26 | } |
59 | 28 | } |
60 | 29 | |
61 | 30 | func (m *FileMutex) TryLock() error { |
62 | var ol syscall.Overlapped | |
63 | if err := lockFileEx(m.fd, lockfileFailImmediately|lockfileExclusiveLock, 0, 1, 0, &ol); err != nil { | |
64 | if errno, ok := err.(syscall.Errno); ok { | |
65 | if errno == syscall.Errno(0x21) { | |
31 | if err := windows.LockFileEx(m.fd, windows.LOCKFILE_FAIL_IMMEDIATELY|windows.LOCKFILE_EXCLUSIVE_LOCK, 0, 1, 0, &windows.Overlapped{}); err != nil { | |
32 | if errno, ok := err.(windows.Errno); ok { | |
33 | if errno == windows.ERROR_LOCK_VIOLATION { | |
66 | 34 | return AlreadyLocked |
67 | 35 | } |
68 | 36 | } |
72 | 40 | } |
73 | 41 | |
74 | 42 | func (m *FileMutex) Lock() error { |
75 | var ol syscall.Overlapped | |
76 | if err := lockFileEx(m.fd, lockfileExclusiveLock, 0, 1, 0, &ol); err != nil { | |
77 | return err | |
78 | } | |
79 | return nil | |
43 | return windows.LockFileEx(m.fd, windows.LOCKFILE_EXCLUSIVE_LOCK, 0, 1, 0, &windows.Overlapped{}) | |
80 | 44 | } |
81 | 45 | |
82 | 46 | func (m *FileMutex) Unlock() error { |
83 | var ol syscall.Overlapped | |
84 | if err := unlockFileEx(m.fd, 0, 1, 0, &ol); err != nil { | |
85 | return err | |
86 | } | |
87 | return nil | |
47 | return windows.UnlockFileEx(m.fd, 0, 1, 0, &windows.Overlapped{}) | |
88 | 48 | } |
89 | 49 | |
90 | 50 | func (m *FileMutex) RLock() error { |
91 | var ol syscall.Overlapped | |
92 | if err := lockFileEx(m.fd, 0, 0, 1, 0, &ol); err != nil { | |
93 | return err | |
94 | } | |
95 | return nil | |
51 | return windows.LockFileEx(m.fd, 0, 0, 1, 0, &windows.Overlapped{}) | |
96 | 52 | } |
97 | 53 | |
98 | 54 | func (m *FileMutex) RUnlock() error { |
99 | var ol syscall.Overlapped | |
100 | if err := unlockFileEx(m.fd, 0, 1, 0, &ol); err != nil { | |
101 | return err | |
102 | } | |
103 | return nil | |
55 | return windows.UnlockFileEx(m.fd, 0, 1, 0, &windows.Overlapped{}) | |
104 | 56 | } |
105 | 57 | |
106 | 58 | // Close unlocks the lock and closes the underlying file descriptor. |
107 | 59 | func (m *FileMutex) Close() error { |
108 | var ol syscall.Overlapped | |
109 | if err := unlockFileEx(m.fd, 0, 1, 0, &ol); err != nil { | |
60 | if err := windows.UnlockFileEx(m.fd, 0, 1, 0, &windows.Overlapped{}); err != nil && err != errLockUnlocked { | |
110 | 61 | return err |
111 | 62 | } |
112 | return syscall.Close(m.fd) | |
63 | return windows.Close(m.fd) | |
113 | 64 | } |
1 | 1 | |
2 | 2 | go 1.13 |
3 | 3 | |
4 | require github.com/stretchr/testify v1.4.0 | |
4 | require ( | |
5 | github.com/stretchr/testify v1.4.0 | |
6 | golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 | |
7 | ) |
4 | 4 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= |
5 | 5 | github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= |
6 | 6 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= |
7 | golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 h1:RqytpXGR1iVNX7psjB3ff8y7sNFinVFvkx1c8SjBkio= | |
8 | golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | |
7 | 9 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= |
8 | 10 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= |
9 | 11 | gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= |