Lock the repository file for concurrent processes synchronization and re-read its content before updating it

Signed-off-by: Patrick Decat <pdecat@gmail.com>
pull/5678/head
Patrick Decat 6 years ago
parent ed9934adfa
commit e07dfcbc00
No known key found for this signature in database
GPG Key ID: FD55B9BD5687D8FF

@ -22,11 +22,12 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"syscall"
"golang.org/x/crypto/ssh/terminal" "golang.org/x/crypto/ssh/terminal"
"k8s.io/helm/pkg/getter" "k8s.io/helm/pkg/getter"
"k8s.io/helm/pkg/helm/helmpath" "k8s.io/helm/pkg/helm/helmpath"
"k8s.io/helm/pkg/repo" "k8s.io/helm/pkg/repo"
"syscall"
) )
type repoAddCmd struct { type repoAddCmd struct {
@ -131,6 +132,30 @@ func addRepository(name, url, username, password string, home helmpath.Home, cer
return fmt.Errorf("Looks like %q is not a valid chart repository or cannot be reached: %s", url, err.Error()) return fmt.Errorf("Looks like %q is not a valid chart repository or cannot be reached: %s", url, err.Error())
} }
// Lock the repository file for concurrent processes synchronization and re-read its content before updating it
fd, err := syscall.Open(home.RepositoryFile(), syscall.O_CREAT|syscall.O_RDWR|syscall.O_CLOEXEC, 0)
if err != nil {
return err
}
defer syscall.Close(fd)
flock := syscall.Flock_t{
Type: syscall.F_WRLCK,
Start: 0,
Len: 0,
Whence: io.SeekStart,
}
syscall.FcntlFlock(uintptr(fd), syscall.F_SETLK, &flock)
if err != nil {
return err
}
f, err = repo.LoadRepositoriesFile(home.RepositoryFile())
if err != nil {
return err
}
f.Update(&c) f.Update(&c)
return f.WriteFile(home.RepositoryFile(), 0644) return f.WriteFile(home.RepositoryFile(), 0644)

@ -128,6 +128,7 @@ func TestRepoAddConcurrentGoRoutines(t *testing.T) {
wg.Add(3) wg.Add(3)
for i := 0; i < 3; i++ { for i := 0; i < 3; i++ {
go func(name string) { go func(name string) {
// TODO: launch repository additions in sub-processes as file locks are bound to processes, not file descriptors
defer wg.Done() defer wg.Done()
if err := addRepository(name, ts.URL(), "", "", settings.Home, "", "", "", true); err != nil { if err := addRepository(name, ts.URL(), "", "", settings.Home, "", "", "", true); err != nil {
t.Error(err) t.Error(err)

Loading…
Cancel
Save