Merge pull request #261 from restic/fix-260

locks: fix testing stale locks created on other hosts
This commit is contained in:
Alexander Neumann 2015-08-18 22:53:52 +02:00
commit cd4cc1daec
2 changed files with 63 additions and 22 deletions

28
lock.go
View file

@ -194,10 +194,30 @@ func (l *Lock) Stale() bool {
return true return true
} }
// check if we can reach the process retaining the lock hn, err := os.Hostname()
exists := l.processExists() if err != nil {
if !exists { debug.Log("Lock.Stale", "unable to find current hostnanme: %v", err)
debug.Log("Lock.Stale", "could not reach process, %d, lock is probably stale\n", l.PID) // since we cannot find the current hostname, assume that the lock is
// not stale.
return false
}
if hn != l.Hostname {
// lock was created on a different host, assume the lock is not stale.
return false
}
proc, err := os.FindProcess(l.PID)
defer proc.Release()
if err != nil {
debug.Log("Lock.Stale", "error searching for process %d: %v\n", l.PID, err)
return true
}
debug.Log("Lock.Stale", "sending SIGHUP to process %d\n", l.PID)
err = proc.Signal(syscall.SIGHUP)
if err != nil {
debug.Log("Lock.Stale", "signal error: %v, lock is probably stale\n", err)
return true return true
} }

View file

@ -93,7 +93,12 @@ func TestExclusiveLockOnLockedRepo(t *testing.T) {
} }
func createFakeLock(repo *repository.Repository, t time.Time, pid int) (backend.ID, error) { func createFakeLock(repo *repository.Repository, t time.Time, pid int) (backend.ID, error) {
newLock := &restic.Lock{Time: t, PID: pid} hostname, err := os.Hostname()
if err != nil {
return backend.ID{}, err
}
newLock := &restic.Lock{Time: t, PID: pid, Hostname: hostname}
return repo.SaveJSONUnpacked(backend.Lock, &newLock) return repo.SaveJSONUnpacked(backend.Lock, &newLock)
} }
@ -104,40 +109,56 @@ func removeLock(repo *repository.Repository, id backend.ID) error {
var staleLockTests = []struct { var staleLockTests = []struct {
timestamp time.Time timestamp time.Time
stale bool stale bool
staleOnOtherHost bool
pid int pid int
}{ }{
{ {
timestamp: time.Now(), timestamp: time.Now(),
stale: false, stale: false,
staleOnOtherHost: false,
pid: os.Getpid(), pid: os.Getpid(),
}, },
{ {
timestamp: time.Now().Add(-time.Hour), timestamp: time.Now().Add(-time.Hour),
stale: true, stale: true,
staleOnOtherHost: true,
pid: os.Getpid(), pid: os.Getpid(),
}, },
{ {
timestamp: time.Now().Add(3 * time.Minute), timestamp: time.Now().Add(3 * time.Minute),
stale: false, stale: false,
staleOnOtherHost: false,
pid: os.Getpid(), pid: os.Getpid(),
}, },
{ {
timestamp: time.Now(), timestamp: time.Now(),
stale: true, stale: true,
pid: os.Getpid() + 500000, staleOnOtherHost: false,
pid: os.Getpid() + 500,
}, },
} }
func TestLockStale(t *testing.T) { func TestLockStale(t *testing.T) {
hostname, err := os.Hostname()
OK(t, err)
otherHostname := "other-" + hostname
for i, test := range staleLockTests { for i, test := range staleLockTests {
lock := restic.Lock{ lock := restic.Lock{
Time: test.timestamp, Time: test.timestamp,
PID: test.pid, PID: test.pid,
Hostname: hostname,
} }
Assert(t, lock.Stale() == test.stale, Assert(t, lock.Stale() == test.stale,
"TestStaleLock: test %d failed: expected stale: %v, got %v", "TestStaleLock: test %d failed: expected stale: %v, got %v",
i, test.stale, !test.stale) i, test.stale, !test.stale)
lock.Hostname = otherHostname
Assert(t, lock.Stale() == test.staleOnOtherHost,
"TestStaleLock: test %d failed: expected staleOnOtherHost: %v, got %v",
i, test.staleOnOtherHost, !test.staleOnOtherHost)
} }
} }