forked from TrueCloudLab/restic
Merge pull request #4022 from MichaelEischer/race-checker
CI: Run the golang race checker
This commit is contained in:
commit
f115d64634
4 changed files with 28 additions and 5 deletions
9
.github/workflows/tests.yml
vendored
9
.github/workflows/tests.yml
vendored
|
@ -37,6 +37,13 @@ jobs:
|
||||||
check_changelog: true
|
check_changelog: true
|
||||||
install_verb: install
|
install_verb: install
|
||||||
|
|
||||||
|
- job_name: Linux (race)
|
||||||
|
go: 1.19.x
|
||||||
|
os: ubuntu-latest
|
||||||
|
test_fuse: true
|
||||||
|
test_opts: "-race"
|
||||||
|
install_verb: install
|
||||||
|
|
||||||
- job_name: Linux
|
- job_name: Linux
|
||||||
go: 1.18.x
|
go: 1.18.x
|
||||||
os: ubuntu-latest
|
os: ubuntu-latest
|
||||||
|
@ -152,7 +159,7 @@ jobs:
|
||||||
env:
|
env:
|
||||||
RESTIC_TEST_FUSE: ${{ matrix.test_fuse }}
|
RESTIC_TEST_FUSE: ${{ matrix.test_fuse }}
|
||||||
run: |
|
run: |
|
||||||
go test -cover ./...
|
go test -cover ${{matrix.test_opts}} ./...
|
||||||
|
|
||||||
- name: Test cloud backends
|
- name: Test cloud backends
|
||||||
env:
|
env:
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -54,7 +55,8 @@ func waitForMount(t testing.TB, dir string) {
|
||||||
t.Errorf("subdir %q of dir %s never appeared", mountTestSubdir, dir)
|
t.Errorf("subdir %q of dir %s never appeared", mountTestSubdir, dir)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testRunMount(t testing.TB, gopts GlobalOptions, dir string) {
|
func testRunMount(t testing.TB, gopts GlobalOptions, dir string, wg *sync.WaitGroup) {
|
||||||
|
defer wg.Done()
|
||||||
opts := MountOptions{
|
opts := MountOptions{
|
||||||
TimeTemplate: time.RFC3339,
|
TimeTemplate: time.RFC3339,
|
||||||
}
|
}
|
||||||
|
@ -87,8 +89,11 @@ func listSnapshots(t testing.TB, dir string) []string {
|
||||||
func checkSnapshots(t testing.TB, global GlobalOptions, repo *repository.Repository, mountpoint, repodir string, snapshotIDs restic.IDs, expectedSnapshotsInFuseDir int) {
|
func checkSnapshots(t testing.TB, global GlobalOptions, repo *repository.Repository, mountpoint, repodir string, snapshotIDs restic.IDs, expectedSnapshotsInFuseDir int) {
|
||||||
t.Logf("checking for %d snapshots: %v", len(snapshotIDs), snapshotIDs)
|
t.Logf("checking for %d snapshots: %v", len(snapshotIDs), snapshotIDs)
|
||||||
|
|
||||||
go testRunMount(t, global, mountpoint)
|
var wg sync.WaitGroup
|
||||||
|
wg.Add(1)
|
||||||
|
go testRunMount(t, global, mountpoint, &wg)
|
||||||
waitForMount(t, mountpoint)
|
waitForMount(t, mountpoint)
|
||||||
|
defer wg.Wait()
|
||||||
defer testRunUmount(t, global, mountpoint)
|
defer testRunUmount(t, global, mountpoint)
|
||||||
|
|
||||||
if !snapshotsDirExists(t, mountpoint) {
|
if !snapshotsDirExists(t, mountpoint) {
|
||||||
|
|
|
@ -26,6 +26,7 @@ import (
|
||||||
// A lock must be refreshed regularly to not be considered stale, this must be
|
// A lock must be refreshed regularly to not be considered stale, this must be
|
||||||
// triggered by regularly calling Refresh.
|
// triggered by regularly calling Refresh.
|
||||||
type Lock struct {
|
type Lock struct {
|
||||||
|
lock sync.Mutex
|
||||||
Time time.Time `json:"time"`
|
Time time.Time `json:"time"`
|
||||||
Exclusive bool `json:"exclusive"`
|
Exclusive bool `json:"exclusive"`
|
||||||
Hostname string `json:"hostname"`
|
Hostname string `json:"hostname"`
|
||||||
|
@ -195,6 +196,8 @@ var StaleLockTimeout = 30 * time.Minute
|
||||||
// older than 30 minutes or if it was created on the current machine and the
|
// older than 30 minutes or if it was created on the current machine and the
|
||||||
// process isn't alive any more.
|
// process isn't alive any more.
|
||||||
func (l *Lock) Stale() bool {
|
func (l *Lock) Stale() bool {
|
||||||
|
l.lock.Lock()
|
||||||
|
defer l.lock.Unlock()
|
||||||
debug.Log("testing if lock %v for process %d is stale", l, l.PID)
|
debug.Log("testing if lock %v for process %d is stale", l, l.PID)
|
||||||
if time.Since(l.Time) > StaleLockTimeout {
|
if time.Since(l.Time) > StaleLockTimeout {
|
||||||
debug.Log("lock is stale, timestamp is too old: %v\n", l.Time)
|
debug.Log("lock is stale, timestamp is too old: %v\n", l.Time)
|
||||||
|
@ -229,12 +232,17 @@ func (l *Lock) Stale() bool {
|
||||||
// timestamp. Afterwards the old lock is removed.
|
// timestamp. Afterwards the old lock is removed.
|
||||||
func (l *Lock) Refresh(ctx context.Context) error {
|
func (l *Lock) Refresh(ctx context.Context) error {
|
||||||
debug.Log("refreshing lock %v", l.lockID)
|
debug.Log("refreshing lock %v", l.lockID)
|
||||||
|
l.lock.Lock()
|
||||||
l.Time = time.Now()
|
l.Time = time.Now()
|
||||||
|
l.lock.Unlock()
|
||||||
id, err := l.createLock(ctx)
|
id, err := l.createLock(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
l.lock.Lock()
|
||||||
|
defer l.lock.Unlock()
|
||||||
|
|
||||||
debug.Log("new lock ID %v", id)
|
debug.Log("new lock ID %v", id)
|
||||||
oldLockID := l.lockID
|
oldLockID := l.lockID
|
||||||
l.lockID = &id
|
l.lockID = &id
|
||||||
|
@ -242,7 +250,10 @@ func (l *Lock) Refresh(ctx context.Context) error {
|
||||||
return l.repo.Backend().Remove(context.TODO(), Handle{Type: LockFile, Name: oldLockID.String()})
|
return l.repo.Backend().Remove(context.TODO(), Handle{Type: LockFile, Name: oldLockID.String()})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l Lock) String() string {
|
func (l *Lock) String() string {
|
||||||
|
l.lock.Lock()
|
||||||
|
defer l.lock.Unlock()
|
||||||
|
|
||||||
text := fmt.Sprintf("PID %d on %s by %s (UID %d, GID %d)\nlock was created at %s (%s ago)\nstorage ID %v",
|
text := fmt.Sprintf("PID %d on %s by %s (UID %d, GID %d)\nlock was created at %s (%s ago)\nstorage ID %v",
|
||||||
l.PID, l.Hostname, l.Username, l.UID, l.GID,
|
l.PID, l.Hostname, l.Username, l.UID, l.GID,
|
||||||
l.Time.Format("2006-01-02 15:04:05"), time.Since(l.Time),
|
l.Time.Format("2006-01-02 15:04:05"), time.Since(l.Time),
|
||||||
|
|
|
@ -29,7 +29,7 @@ func uidGidInt(u *user.User) (uid, gid uint32, err error) {
|
||||||
// checkProcess will check if the process retaining the lock
|
// checkProcess will check if the process retaining the lock
|
||||||
// exists and responds to SIGHUP signal.
|
// exists and responds to SIGHUP signal.
|
||||||
// Returns true if the process exists and responds.
|
// Returns true if the process exists and responds.
|
||||||
func (l Lock) processExists() bool {
|
func (l *Lock) processExists() bool {
|
||||||
proc, err := os.FindProcess(l.PID)
|
proc, err := os.FindProcess(l.PID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
debug.Log("error searching for process %d: %v\n", l.PID, err)
|
debug.Log("error searching for process %d: %v\n", l.PID, err)
|
||||||
|
|
Loading…
Reference in a new issue