Example #1
0
func (ts *FileLockTestSuite) TestWithLockSimple(c *C) {
	called := false
	path := filepath.Join(c.MkDir(), "lock")

	err := lockfile.WithLock(path, func() error {
		called = true
		return nil
	})

	c.Assert(err, IsNil)
	c.Assert(called, Equals, true)
}
Example #2
0
func (ts *FileLockTestSuite) TestWithLockErrOnLockHeld(c *C) {

	var err, err1, err2 error
	var callCount int

	slowFunc := func() error {
		time.Sleep(time.Millisecond * 100)
		callCount++
		return nil
	}

	path := filepath.Join(c.MkDir(), "lock")
	ch := make(chan bool)
	go func() {
		err1 = lockfile.WithLock(path, slowFunc)
		ch <- true
	}()
	err2 = lockfile.WithLock(path, slowFunc)
	// wait for the goroutine
	<-ch

	// find which err is set (depends on the order in which go
	// runs the goroutine)
	if err1 != nil {
		err = err1
	} else {
		err = err2
	}

	// only one of the functions errored
	c.Assert(err1 != nil && err2 != nil, Equals, false)
	// the other returned a proper error
	c.Assert(err, Equals, lockfile.ErrAlreadyLocked)
	// and we did not call it too often
	c.Assert(callCount, Equals, 1)
}
Example #3
0
// withMutexAndRetry runs the given function with a filelock mutex and provides
// automatic re-try and helpful messages if the lock is already taken
func withMutexAndRetry(f func() error) error {
	if sys.Getuid() != 0 {
		return snappy.ErrNeedRoot
	}
	for {
		err := lockfile.WithLock(dirs.SnapLockFile, f)
		// if already locked, auto-retry
		if err == lockfile.ErrAlreadyLocked {
			var msg string
			if isAutoUpdateRunning() {
				// FIXME: we could even do a
				//    journalctl -u snappy-autopilot
				// here

				// TRANSLATORS: please keep each line under 80 characters.
				msg = i18n.G(
					`Snappy is updating your system in the background. This may take some minutes.
Will try again in %d seconds...
Press ctrl-c to cancel.
`)
			} else {
				msg = i18n.G(
					`Another snappy is running, will try again in %d seconds...
Press ctrl-c to cancel.
`)
			}
			// wait a wee bit
			wait := 5
			fmt.Printf(msg, wait)
			time.Sleep(time.Duration(wait) * time.Second)
			continue
		}

		return err
	}
}