Lock the repository file for concurrent processes synchronization and re-read…

Lock the repository file for concurrent processes synchronization and re-read its content before updating it
Signed-off-by: 's avatarPatrick Decat <pdecat@gmail.com>
parent ed9934ad
......@@ -22,11 +22,12 @@ import (
"github.com/spf13/cobra"
"syscall"
"golang.org/x/crypto/ssh/terminal"
"k8s.io/helm/pkg/getter"
"k8s.io/helm/pkg/helm/helmpath"
"k8s.io/helm/pkg/repo"
"syscall"
)
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())
}
// 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)
return f.WriteFile(home.RepositoryFile(), 0644)
......
......@@ -128,6 +128,7 @@ func TestRepoAddConcurrentGoRoutines(t *testing.T) {
wg.Add(3)
for i := 0; i < 3; i++ {
go func(name string) {
// TODO: launch repository additions in sub-processes as file locks are bound to processes, not file descriptors
defer wg.Done()
if err := addRepository(name, ts.URL(), "", "", settings.Home, "", "", "", true); err != nil {
t.Error(err)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment