Skip to content

Commit

Permalink
lockedfile: update from Go master
Browse files Browse the repository at this point in the history
Code taken from upstream commit d7dbe0111ef2a6de80a20fef188db61d8fab5c96.
  • Loading branch information
rogpeppe committed Nov 10, 2022
1 parent 645eaf1 commit 1d22f4b
Show file tree
Hide file tree
Showing 13 changed files with 238 additions and 75 deletions.
5 changes: 3 additions & 2 deletions lockedfile/internal/filelock/filelock.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ package filelock

import (
"errors"
"io/fs"
"os"
)

Expand All @@ -24,7 +25,7 @@ type File interface {
Fd() uintptr

// Stat returns the FileInfo structure describing file.
Stat() (os.FileInfo, error)
Stat() (fs.FileInfo, error)
}

// Lock places an advisory write lock on the file, blocking until it can be
Expand Down Expand Up @@ -87,7 +88,7 @@ var ErrNotSupported = errors.New("operation not supported")
// underlyingError returns the underlying error for known os error types.
func underlyingError(err error) error {
switch err := err.(type) {
case *os.PathError:
case *fs.PathError:
return err.Err
case *os.LinkError:
return err.Err
Expand Down
15 changes: 5 additions & 10 deletions lockedfile/internal/filelock/filelock_fcntl.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//go:build aix || solaris
// +build aix solaris
//go:build aix || (solaris && !illumos)
// +build aix solaris,!illumos

// This code implements the filelock API using POSIX 'fcntl' locks, which attach
// to an (inode, process) pair rather than a file descriptor. To avoid unlocking
Expand All @@ -13,17 +13,14 @@
// Most platforms provide some alternative API, such as an 'flock' system call
// or an F_OFD_SETLK command for 'fcntl', that allows for better concurrency and
// does not require per-inode bookkeeping in the application.
//
// TODO(golang.org/issue/35618): add a syscall.Flock binding for Illumos and
// switch it over to use filelock_unix.go.

package filelock

import (
"errors"
"io"
"io/fs"
"math/rand"
"os"
"sync"
"syscall"
"time"
Expand All @@ -43,8 +40,6 @@ type inodeLock struct {
queue []<-chan File
}

type token struct{}

var (
mu sync.Mutex
inodes = map[File]inode{}
Expand All @@ -65,7 +60,7 @@ func lock(f File, lt lockType) (err error) {
mu.Lock()
if i, dup := inodes[f]; dup && i != ino {
mu.Unlock()
return &os.PathError{
return &fs.PathError{
Op: lt.String(),
Path: f.Name(),
Err: errors.New("inode for file changed since last Lock or RLock"),
Expand Down Expand Up @@ -156,7 +151,7 @@ func lock(f File, lt lockType) (err error) {

if err != nil {
unlock(f)
return &os.PathError{
return &fs.PathError{
Op: lt.String(),
Path: f.Name(),
Err: err,
Expand Down
6 changes: 3 additions & 3 deletions lockedfile/internal/filelock/filelock_other.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

package filelock

import "os"
import "io/fs"

type lockType int8

Expand All @@ -17,15 +17,15 @@ const (
)

func lock(f File, lt lockType) error {
return &os.PathError{
return &fs.PathError{
Op: lt.String(),
Path: f.Name(),
Err: ErrNotSupported,
}
}

func unlock(f File) error {
return &os.PathError{
return &fs.PathError{
Op: "Unlock",
Path: f.Name(),
Err: ErrNotSupported,
Expand Down
8 changes: 3 additions & 5 deletions lockedfile/internal/filelock/filelock_plan9.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@

package filelock

import (
"os"
)
import "io/fs"

type lockType int8

Expand All @@ -19,15 +17,15 @@ const (
)

func lock(f File, lt lockType) error {
return &os.PathError{
return &fs.PathError{
Op: lt.String(),
Path: f.Name(),
Err: ErrNotSupported,
}
}

func unlock(f File) error {
return &os.PathError{
return &fs.PathError{
Op: "Unlock",
Path: f.Name(),
Err: ErrNotSupported,
Expand Down
22 changes: 10 additions & 12 deletions lockedfile/internal/filelock/filelock_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,20 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//go:build !js && !nacl && !plan9
// +build !js,!nacl,!plan9
//go:build !js && !plan9
// +build !js,!plan9

package filelock_test

import (
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"runtime"
"testing"
"time"

"github.com/rogpeppe/go-internal/testenv"

"github.com/rogpeppe/go-internal/lockedfile/internal/filelock"
)

Expand Down Expand Up @@ -53,9 +50,9 @@ func mustTempFile(t *testing.T) (f *os.File, remove func()) {
t.Helper()

base := filepath.Base(t.Name())
f, err := ioutil.TempFile("", base)
f, err := os.CreateTemp("", base)
if err != nil {
t.Fatalf(`ioutil.TempFile("", %q) = %v`, base, err)
t.Fatalf(`os.CreateTemp("", %q) = %v`, base, err)
}
t.Logf("fd %d = %s", f.Fd(), f.Name())

Expand Down Expand Up @@ -161,33 +158,34 @@ func TestRLockExcludesOnlyLock(t *testing.T) {
f2 := mustOpen(t, f.Name())
defer f2.Close()

if runtime.GOOS == "solaris" || runtime.GOOS == "aix" {
doUnlockTF := false
switch runtime.GOOS {
case "aix", "solaris":
// When using POSIX locks (as on Solaris), we can't safely read-lock the
// same inode through two different descriptors at the same time: when the
// first descriptor is closed, the second descriptor would still be open but
// silently unlocked. So a second RLock must block instead of proceeding.
lockF2 := mustBlock(t, "RLock", f2)
unlock(t, f)
lockF2(t)
} else {
default:
rLock(t, f2)
doUnlockTF = true
}

other := mustOpen(t, f.Name())
defer other.Close()
lockOther := mustBlock(t, "Lock", other)

unlock(t, f2)
if runtime.GOOS != "solaris" && runtime.GOOS != "aix" {
if doUnlockTF {
unlock(t, f)
}
lockOther(t)
unlock(t, other)
}

func TestLockNotDroppedByExecCommand(t *testing.T) {
testenv.MustHaveExec(t)

f, remove := mustTempFile(t)
defer remove()

Expand Down
8 changes: 4 additions & 4 deletions lockedfile/internal/filelock/filelock_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd
// +build darwin dragonfly freebsd linux netbsd openbsd
//go:build darwin || dragonfly || freebsd || illumos || linux || netbsd || openbsd
// +build darwin dragonfly freebsd illumos linux netbsd openbsd

package filelock

import (
"os"
"io/fs"
"syscall"
)

Expand All @@ -27,7 +27,7 @@ func lock(f File, lt lockType) (err error) {
}
}
if err != nil {
return &os.PathError{
return &fs.PathError{
Op: lt.String(),
Path: f.Name(),
Err: err,
Expand Down
9 changes: 4 additions & 5 deletions lockedfile/internal/filelock/filelock_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,9 @@
package filelock

import (
"os"
"internal/syscall/windows"
"io/fs"
"syscall"

"github.com/rogpeppe/go-internal/internal/syscall/windows"
)

type lockType uint32
Expand All @@ -36,7 +35,7 @@ func lock(f File, lt lockType) error {

err := windows.LockFileEx(syscall.Handle(f.Fd()), uint32(lt), reserved, allBytes, allBytes, ol)
if err != nil {
return &os.PathError{
return &fs.PathError{
Op: lt.String(),
Path: f.Name(),
Err: err,
Expand All @@ -49,7 +48,7 @@ func unlock(f File) error {
ol := new(syscall.Overlapped)
err := windows.UnlockFileEx(syscall.Handle(f.Fd()), reserved, allBytes, allBytes, ol)
if err != nil {
return &os.PathError{
return &fs.PathError{
Op: "Unlock",
Path: f.Name(),
Err: err,
Expand Down

0 comments on commit 1d22f4b

Please sign in to comment.