From 9753aae065e2c954d4c5c321b15e1e122c625cde Mon Sep 17 00:00:00 2001 From: Marius Date: Fri, 30 Sep 2016 12:03:49 +0200 Subject: [PATCH] Use personal fork of nightlyone/filelock --- filestore/filestore.go | 2 +- .../nightlyone/lockfile/lockfile.go | 196 ------------------ .../Acconut/lockfile.v1}/LICENSE | 0 .../Acconut/lockfile.v1}/README.md | 0 .../Acconut/lockfile.v1}/appveyor.yml | 0 .../gopkg.in/Acconut/lockfile.v1/lockfile.go | 135 ++++++++++++ .../Acconut/lockfile.v1}/lockfile_unix.go | 12 +- .../Acconut/lockfile.v1}/lockfile_windows.go | 0 vendor/vendor.json | 12 +- 9 files changed, 149 insertions(+), 208 deletions(-) delete mode 100644 vendor/github.com/nightlyone/lockfile/lockfile.go rename vendor/{github.com/nightlyone/lockfile => gopkg.in/Acconut/lockfile.v1}/LICENSE (100%) rename vendor/{github.com/nightlyone/lockfile => gopkg.in/Acconut/lockfile.v1}/README.md (100%) rename vendor/{github.com/nightlyone/lockfile => gopkg.in/Acconut/lockfile.v1}/appveyor.yml (100%) create mode 100644 vendor/gopkg.in/Acconut/lockfile.v1/lockfile.go rename vendor/{github.com/nightlyone/lockfile => gopkg.in/Acconut/lockfile.v1}/lockfile_unix.go (65%) rename vendor/{github.com/nightlyone/lockfile => gopkg.in/Acconut/lockfile.v1}/lockfile_windows.go (100%) diff --git a/filestore/filestore.go b/filestore/filestore.go index 1d82e55..ad52a7e 100644 --- a/filestore/filestore.go +++ b/filestore/filestore.go @@ -25,7 +25,7 @@ import ( "github.com/tus/tusd" "github.com/tus/tusd/uid" - "github.com/nightlyone/lockfile" + "gopkg.in/Acconut/lockfile.v1" ) var defaultFilePerm = os.FileMode(0664) diff --git a/vendor/github.com/nightlyone/lockfile/lockfile.go b/vendor/github.com/nightlyone/lockfile/lockfile.go deleted file mode 100644 index 82f5093..0000000 --- a/vendor/github.com/nightlyone/lockfile/lockfile.go +++ /dev/null @@ -1,196 +0,0 @@ -// Package lockfile handles pid file based locking. -package lockfile - -import ( - "errors" - "fmt" - "io" - "io/ioutil" - "os" - "path/filepath" -) - -// Lockfile is a pid file which can be locked -type Lockfile string - -// TemporaryError is a type of error where a retry after a random amount of sleep should help to mitigate it. -type TemporaryError string - -func (t TemporaryError) Error() string { return string(t) } - -// Temporary returns always true. -// It exists, so you can detect it via -// if te, ok := err.(interface{ Temporary() bool }); ok { -// fmt.Println("I am a temporay error situation, so wait and retry") -// } -func (t TemporaryError) Temporary() bool { return true } - -// Various errors returned by this package -var ( - ErrBusy = TemporaryError("Locked by other process") // If you get this, retry after a short sleep might help - ErrNotExist = TemporaryError("Lockfile created, but doesn't exist") // If you get this, retry after a short sleep might help - ErrNeedAbsPath = errors.New("Lockfiles must be given as absolute path names") - ErrInvalidPid = errors.New("Lockfile contains invalid pid for system") - ErrDeadOwner = errors.New("Lockfile contains pid of process not existent on this system anymore") - ErrRogueDeletion = errors.New("Lockfile owned by me has been removed unexpectedly") -) - -// New describes a new filename located at the given absolute path. -func New(path string) (Lockfile, error) { - if !filepath.IsAbs(path) { - return Lockfile(""), ErrNeedAbsPath - } - return Lockfile(path), nil -} - -// GetOwner returns who owns the lockfile. -func (l Lockfile) GetOwner() (*os.Process, error) { - name := string(l) - - // Ok, see, if we have a stale lockfile here - content, err := ioutil.ReadFile(name) - if err != nil { - return nil, err - } - - // try hard for pids. If no pid, the lockfile is junk anyway and we delete it. - pid, err := scanPidLine(content) - if err != nil { - return nil, err - } - running, err := isRunning(pid) - if err != nil { - return nil, err - } - - if running { - proc, err := os.FindProcess(pid) - if err != nil { - return nil, err - } - return proc, nil - } - return nil, ErrDeadOwner - -} - -// TryLock tries to own the lock. -// It Returns nil, if successful and and error describing the reason, it didn't work out. -// Please note, that existing lockfiles containing pids of dead processes -// and lockfiles containing no pid at all are simply deleted. -func (l Lockfile) TryLock() error { - name := string(l) - - // This has been checked by New already. If we trigger here, - // the caller didn't use New and re-implemented it's functionality badly. - // So panic, that he might find this easily during testing. - if !filepath.IsAbs(name) { - panic(ErrNeedAbsPath) - } - - tmplock, err := ioutil.TempFile(filepath.Dir(name), "") - if err != nil { - return err - } - - cleanup := func() { - _ = tmplock.Close() - _ = os.Remove(tmplock.Name()) - } - defer cleanup() - - if err := writePidLine(tmplock, os.Getpid()); err != nil { - return err - } - - // return value intentionally ignored, as ignoring it is part of the algorithm - _ = os.Link(tmplock.Name(), name) - - fiTmp, err := os.Lstat(tmplock.Name()) - if err != nil { - return err - } - fiLock, err := os.Lstat(name) - if err != nil { - // tell user that a retry would be a good idea - if os.IsNotExist(err) { - return ErrNotExist - } - return err - } - - // Success - if os.SameFile(fiTmp, fiLock) { - return nil - } - - proc, err := l.GetOwner() - switch err { - default: - // Other errors -> defensively fail and let caller handle this - return err - case nil: - if proc.Pid != os.Getpid() { - return ErrBusy - } - case ErrDeadOwner, ErrInvalidPid: - // cases we can fix below - } - - // clean stale/invalid lockfile - err = os.Remove(name) - if err != nil { - // If it doesn't exist, then it doesn't matter who removed it. - if !os.IsNotExist(err) { - return err - } - } - - // now that the stale lockfile is gone, let's recurse - return l.TryLock() -} - -// Unlock a lock again, if we owned it. Returns any error that happend during release of lock. -func (l Lockfile) Unlock() error { - proc, err := l.GetOwner() - switch err { - case ErrInvalidPid, ErrDeadOwner: - return ErrRogueDeletion - case nil: - if proc.Pid == os.Getpid() { - // we really own it, so let's remove it. - return os.Remove(string(l)) - } - // Not owned by me, so don't delete it. - return ErrRogueDeletion - default: - // This is an application error or system error. - // So give a better error for logging here. - if os.IsNotExist(err) { - return ErrRogueDeletion - } - // Other errors -> defensively fail and let caller handle this - return err - } -} - -func writePidLine(w io.Writer, pid int) error { - _, err := io.WriteString(w, fmt.Sprintf("%d\n", pid)) - return err -} - -func scanPidLine(content []byte) (int, error) { - if len(content) == 0 { - return 0, ErrInvalidPid - } - - var pid int - if _, err := fmt.Sscanln(string(content), &pid); err != nil { - return 0, ErrInvalidPid - } - - if pid <= 0 { - return 0, ErrInvalidPid - } - return pid, nil -} diff --git a/vendor/github.com/nightlyone/lockfile/LICENSE b/vendor/gopkg.in/Acconut/lockfile.v1/LICENSE similarity index 100% rename from vendor/github.com/nightlyone/lockfile/LICENSE rename to vendor/gopkg.in/Acconut/lockfile.v1/LICENSE diff --git a/vendor/github.com/nightlyone/lockfile/README.md b/vendor/gopkg.in/Acconut/lockfile.v1/README.md similarity index 100% rename from vendor/github.com/nightlyone/lockfile/README.md rename to vendor/gopkg.in/Acconut/lockfile.v1/README.md diff --git a/vendor/github.com/nightlyone/lockfile/appveyor.yml b/vendor/gopkg.in/Acconut/lockfile.v1/appveyor.yml similarity index 100% rename from vendor/github.com/nightlyone/lockfile/appveyor.yml rename to vendor/gopkg.in/Acconut/lockfile.v1/appveyor.yml diff --git a/vendor/gopkg.in/Acconut/lockfile.v1/lockfile.go b/vendor/gopkg.in/Acconut/lockfile.v1/lockfile.go new file mode 100644 index 0000000..bb5c221 --- /dev/null +++ b/vendor/gopkg.in/Acconut/lockfile.v1/lockfile.go @@ -0,0 +1,135 @@ +// Handle pid file based locking. +package lockfile + +import ( + "errors" + "fmt" + "io/ioutil" + "os" + "path/filepath" +) + +type Lockfile string + +var ( + ErrBusy = errors.New("Locked by other process") // If you get this, retry after a short sleep might help + ErrNeedAbsPath = errors.New("Lockfiles must be given as absolute path names") + ErrInvalidPid = errors.New("Lockfile contains invalid pid for system") + ErrDeadOwner = errors.New("Lockfile contains pid of process not existent on this system anymore") +) + +// Describe a new filename located at path. It is expected to be an absolute path +func New(path string) (Lockfile, error) { + if !filepath.IsAbs(path) { + return Lockfile(""), ErrNeedAbsPath + } + return Lockfile(path), nil +} + +// Who owns the lockfile? +func (l Lockfile) GetOwner() (*os.Process, error) { + name := string(l) + + // Ok, see, if we have a stale lockfile here + content, err := ioutil.ReadFile(name) + if err != nil { + return nil, err + } + + var pid int + _, err = fmt.Sscanln(string(content), &pid) + if err != nil { + return nil, ErrInvalidPid + } + + // try hard for pids. If no pid, the lockfile is junk anyway and we delete it. + if pid > 0 { + running, err := isRunning(pid) + if err != nil { + return nil, err + } + + if running { + proc, err := os.FindProcess(pid) + if err != nil { + return nil, err + } + return proc, nil + } else { + return nil, ErrDeadOwner + } + + } else { + return nil, ErrInvalidPid + } + panic("Not reached") +} + +// Try to get Lockfile lock. Returns nil, if successful and and error describing the reason, it didn't work out. +// Please note, that existing lockfiles containing pids of dead processes and lockfiles containing no pid at all +// are deleted. +func (l Lockfile) TryLock() error { + name := string(l) + + // This has been checked by New already. If we trigger here, + // the caller didn't use New and re-implemented it's functionality badly. + // So panic, that he might find this easily during testing. + if !filepath.IsAbs(string(name)) { + panic(ErrNeedAbsPath) + } + + tmplock, err := ioutil.TempFile(filepath.Dir(name), "") + if err != nil { + return err + } else { + defer tmplock.Close() + defer os.Remove(tmplock.Name()) + } + + _, err = tmplock.WriteString(fmt.Sprintf("%d\n", os.Getpid())) + if err != nil { + return err + } + + // return value intentionally ignored, as ignoring it is part of the algorithm + _ = os.Link(tmplock.Name(), name) + + fiTmp, err := os.Lstat(tmplock.Name()) + if err != nil { + return err + } + fiLock, err := os.Lstat(name) + if err != nil { + return err + } + + // Success + if os.SameFile(fiTmp, fiLock) { + return nil + } + + _, err = l.GetOwner() + switch err { + default: + // Other errors -> defensively fail and let caller handle this + return err + case nil: + return ErrBusy + case ErrDeadOwner, ErrInvalidPid: + // cases we can fix below + } + + // clean stale/invalid lockfile + err = os.Remove(name) + if err != nil { + return err + } + + // now that we cleaned up the stale lockfile, let's recurse + return l.TryLock() +} + +// Release a lock again. Returns any error that happend during release of lock. +func (l Lockfile) Unlock() error { + return os.Remove(string(l)) +} diff --git a/vendor/github.com/nightlyone/lockfile/lockfile_unix.go b/vendor/gopkg.in/Acconut/lockfile.v1/lockfile_unix.go similarity index 65% rename from vendor/github.com/nightlyone/lockfile/lockfile_unix.go rename to vendor/gopkg.in/Acconut/lockfile.v1/lockfile_unix.go index 742b041..36c46eb 100644 --- a/vendor/github.com/nightlyone/lockfile/lockfile_unix.go +++ b/vendor/gopkg.in/Acconut/lockfile.v1/lockfile_unix.go @@ -11,10 +11,12 @@ func isRunning(pid int) (bool, error) { proc, err := os.FindProcess(pid) if err != nil { return false, err + } else { + err := proc.Signal(syscall.Signal(0)) + if err == nil { + return true, nil + } else { + return false, nil + } } - - if err := proc.Signal(syscall.Signal(0)); err != nil { - return false, nil - } - return true, nil } diff --git a/vendor/github.com/nightlyone/lockfile/lockfile_windows.go b/vendor/gopkg.in/Acconut/lockfile.v1/lockfile_windows.go similarity index 100% rename from vendor/github.com/nightlyone/lockfile/lockfile_windows.go rename to vendor/gopkg.in/Acconut/lockfile.v1/lockfile_windows.go diff --git a/vendor/vendor.json b/vendor/vendor.json index a996952..bff729e 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -38,12 +38,6 @@ "revision": "c12348ce28de40eed0136aa2b644d0ee0650e56c", "revisionTime": "2016-04-24T11:30:07Z" }, - { - "checksumSHA1": "dSCW0yEU+VThfWk5v/GkSdrjIu4=", - "path": "github.com/nightlyone/lockfile", - "revision": "3d299f51e376213fcdcfd213a76afce6b290bf9d", - "revisionTime": "2016-06-19T19:46:32Z" - }, { "checksumSHA1": "LuFv4/jlrmFNnDb/5SCSEPAM9vU=", "path": "github.com/pmezard/go-difflib/difflib", @@ -91,6 +85,12 @@ "path": "github.com/stretchr/testify/assert", "revision": "d77da356e56a7428ad25149ca77381849a6a5232", "revisionTime": "2016-06-15T09:26:46Z" + }, + { + "checksumSHA1": "0zBf3a7Gzqypt1sWefwx4NkOEIc=", + "path": "gopkg.in/Acconut/lockfile.v1", + "revision": "941fc61ce4d67dd432b94ed0bd445ad5fb9391a9", + "revisionTime": "2016-05-20T15:30:20Z" } ], "rootPath": "github.com/tus/tusd"