Merge pull request #957 from saschagrunert/panic-fix
Fix runtime panic for opening lockfile if parent dir got removed
This commit is contained in:
commit
33b3369a7f
|
|
@ -5,6 +5,7 @@ package lockfile
|
|||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
|
|
@ -33,11 +34,30 @@ type lockfile struct {
|
|||
// descriptor. Note that the path is opened read-only when ro is set. If ro
|
||||
// is unset, openLock will open the path read-write and create the file if
|
||||
// necessary.
|
||||
func openLock(path string, ro bool) (int, error) {
|
||||
func openLock(path string, ro bool) (fd int, err error) {
|
||||
if ro {
|
||||
return unix.Open(path, os.O_RDONLY|unix.O_CLOEXEC, 0)
|
||||
fd, err = unix.Open(path, os.O_RDONLY|unix.O_CLOEXEC, 0)
|
||||
} else {
|
||||
fd, err = unix.Open(path,
|
||||
os.O_RDWR|unix.O_CLOEXEC|os.O_CREATE,
|
||||
unix.S_IRUSR|unix.S_IWUSR|unix.S_IRGRP|unix.S_IROTH,
|
||||
)
|
||||
}
|
||||
return unix.Open(path, os.O_RDWR|unix.O_CLOEXEC|os.O_CREATE, unix.S_IRUSR|unix.S_IWUSR|unix.S_IRGRP|unix.S_IROTH)
|
||||
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// the directory of the lockfile seems to be removed, try to create it
|
||||
if os.IsNotExist(err) {
|
||||
if err := os.MkdirAll(filepath.Dir(path), 0700); err != nil {
|
||||
return fd, errors.Wrap(err, "creating locker directory")
|
||||
}
|
||||
|
||||
return openLock(path, ro)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// createLockerForPath returns a Locker object, possibly (depending on the platform)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,65 @@
|
|||
// +build linux solaris darwin freebsd
|
||||
|
||||
package lockfile
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestOpenLock(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
prepare func() (path string, readOnly bool)
|
||||
}{
|
||||
{
|
||||
name: "file exists (read/write)",
|
||||
prepare: func() (string, bool) {
|
||||
tempFile, err := ioutil.TempFile("", "lock-")
|
||||
require.NoError(t, err)
|
||||
return tempFile.Name(), false
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "file exists readonly (readonly)",
|
||||
prepare: func() (string, bool) {
|
||||
tempFile, err := ioutil.TempFile("", "lock-")
|
||||
require.NoError(t, err)
|
||||
return tempFile.Name(), true
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "base dir exists (read/write)",
|
||||
prepare: func() (string, bool) {
|
||||
tempDir := os.TempDir()
|
||||
require.DirExists(t, tempDir)
|
||||
return filepath.Join(tempDir, "test-1.lock"), false
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "base dir not exists (read/write)",
|
||||
prepare: func() (string, bool) {
|
||||
tempDir, err := ioutil.TempDir("", "lock-")
|
||||
require.NoError(t, err)
|
||||
return filepath.Join(tempDir, "subdir", "test-1.lock"), false
|
||||
},
|
||||
},
|
||||
} {
|
||||
path, readOnly := tc.prepare()
|
||||
|
||||
_, err := openLock(path, readOnly)
|
||||
|
||||
require.NoError(t, err, tc.name)
|
||||
|
||||
_, err = openLock(path, readOnly)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Nil(t, os.RemoveAll(path))
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue