diff --git a/.docker.metadata b/.docker.metadata index 22e1fa5..d1e3dff 100644 --- a/.docker.metadata +++ b/.docker.metadata @@ -5,6 +5,6 @@ c5e6169ea101c97d94257f48fa227f5ff0501454 SOURCES/docker-lvm-plugin-20a1f68.tar.g 0beb6283e30f1e87e907576f4571ccb0a48b6be5 SOURCES/docker-novolume-plugin-385ec70.tar.gz 656b1d1605dc43d7f5c00cedadd686dbd418d285 SOURCES/libnetwork-c5d66a0.tar.gz 965d64f5a81c3a428ca3b29495ecf66748c67c1f SOURCES/rhel-push-plugin-af9107b.tar.gz -671e9be27aaef6c534eba2f7cca4c6fbc75613b6 SOURCES/runc-9c3c5f8.tar.gz +91283894c5ad54b46a8e2f9561cd4468f044502d SOURCES/runc-e45dd70.tar.gz 7941233b1ed34afdc074e74ab26a86dea20ee7d4 SOURCES/tini-fec3683.tar.gz 496f9927f4254508ea1cd94f473b5b9321d41245 SOURCES/v1.10-migrator-c417a6a.tar.gz diff --git a/.gitignore b/.gitignore index 7d81677..df4f729 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,6 @@ SOURCES/docker-lvm-plugin-20a1f68.tar.gz SOURCES/docker-novolume-plugin-385ec70.tar.gz SOURCES/libnetwork-c5d66a0.tar.gz SOURCES/rhel-push-plugin-af9107b.tar.gz -SOURCES/runc-9c3c5f8.tar.gz +SOURCES/runc-e45dd70.tar.gz SOURCES/tini-fec3683.tar.gz SOURCES/v1.10-migrator-c417a6a.tar.gz diff --git a/README.debrand b/README.debrand deleted file mode 100644 index 01c46d2..0000000 --- a/README.debrand +++ /dev/null @@ -1,2 +0,0 @@ -Warning: This package was configured for automatic debranding, but the changes -failed to apply. diff --git a/SOURCES/69518f0bbdb1f11113f46a4d794e09e2f21f5e91.patch b/SOURCES/69518f0bbdb1f11113f46a4d794e09e2f21f5e91.patch new file mode 100644 index 0000000..90ce818 --- /dev/null +++ b/SOURCES/69518f0bbdb1f11113f46a4d794e09e2f21f5e91.patch @@ -0,0 +1,46 @@ +From 69518f0bbdb1f11113f46a4d794e09e2f21f5e91 Mon Sep 17 00:00:00 2001 +From: Ulrich Obergfell +Date: Thu, 10 Oct 2019 11:59:44 +0200 +Subject: [PATCH] fix error handling in restore() function - version 2 + +If runtime.Load() returns an error, the restore() function removes the +/run/docker/libcontainerd/containerd/CONTAINERID directory recursively. +However, this is wrong if the error is not related to the init process +of the container. + +This patch introduces the following changes to the runtime.Load() function: + +- runtime.Load() handles errors from readProcessState() autonomously. The + /run/docker/libcontainerd/containerd/CONTAINERID/PROCESSID directory will + be removed recursively, and a warning message will be logged. + +- Errors returned by runtime.Load() are always related to the init process, + so restore() may remove /run/docker/libcontainerd/containerd/CONTAINERID. + +Signed-off-by: Ulrich Obergfell +--- + runtime/container.go | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/runtime/container.go b/runtime/container.go +index 2e9e663..489e407 100644 +--- a/runtime/container.go ++++ b/runtime/container.go +@@ -182,11 +182,14 @@ func Load(root, id, shimName string, timeout time.Duration) (Container, error) { + continue + } + pid := d.Name() +- s, err := readProcessState(filepath.Join(root, id, pid)) ++ processStateDir := filepath.Join(root, id, pid) ++ s, err := readProcessState(processStateDir) + if err != nil { +- return nil, err ++ logrus.WithFields(logrus.Fields{"error": err, "pid": pid}).Warnf("containerd: failed to load exec process,removing state directory.") ++ os.RemoveAll(processStateDir) ++ continue + } +- p, err := loadProcess(filepath.Join(root, id, pid), pid, c, s) ++ p, err := loadProcess(processStateDir, pid, c, s) + if err != nil { + logrus.WithField("id", id).WithField("pid", pid).Debugf("containerd: error loading process %s", err) + continue diff --git a/SOURCES/6eadd954e5a02f2dcf93928484d42f86b6975618.patch b/SOURCES/6eadd954e5a02f2dcf93928484d42f86b6975618.patch new file mode 100644 index 0000000..21adaef --- /dev/null +++ b/SOURCES/6eadd954e5a02f2dcf93928484d42f86b6975618.patch @@ -0,0 +1,118 @@ +From 6eadd954e5a02f2dcf93928484d42f86b6975618 Mon Sep 17 00:00:00 2001 +From: TomSweeneyRedHat +Date: Fri, 4 Oct 2019 15:44:20 -0400 +Subject: [PATCH] Fix Docker search race/panic - BZ1732626 - 1.13.1 + +Signed-off-by: TomSweeneyRedHat +--- + registry/service.go | 34 ++++++++++++++++++---------------- + 1 file changed, 18 insertions(+), 16 deletions(-) + +diff --git a/registry/service.go b/registry/service.go +index f4b7d65d1dba..cc43987a6a9a 100644 +--- a/registry/service.go ++++ b/registry/service.go +@@ -188,9 +188,9 @@ func getSearchResultsCmpFunc(withIndex bool) by { + return less + } + +-func (s *DefaultService) searchTerm(term string, limit int, authConfigs map[string]types.AuthConfig, userAgent string, headers map[string][]string, noIndex bool, outs *[]registrytypes.SearchResultExt) error { ++func (s *DefaultService) searchTerm(term string, limit int, authConfigs map[string]types.AuthConfig, userAgent string, headers map[string][]string, noIndex bool, outs []registrytypes.SearchResultExt) ([]registrytypes.SearchResultExt, error) { + if err := validateNoScheme(term); err != nil { +- return err ++ return outs, err + } + + indexName, remoteName := splitReposSearchTerm(term, true) +@@ -201,13 +201,13 @@ func (s *DefaultService) searchTerm(term string, limit int, authConfigs map[stri + s.mu.Unlock() + + if err != nil { +- return err ++ return outs, err + } + + // *TODO: Search multiple indexes. + endpoint, err := NewV1Endpoint(index, userAgent, http.Header(headers)) + if err != nil { +- return err ++ return outs, err + } + + ac := ResolveAuthConfig(authConfigs, index) +@@ -228,7 +228,7 @@ func (s *DefaultService) searchTerm(term string, limit int, authConfigs map[stri + if fErr, ok := err.(fallbackError); ok { + logrus.Errorf("Cannot use identity token for search, v2 auth not supported: %v", fErr.err) + } else { +- return err ++ return outs, err + } + } else if foundV2 { + // Copy non transport http client features +@@ -244,13 +244,13 @@ func (s *DefaultService) searchTerm(term string, limit int, authConfigs map[stri + if client == nil { + client = endpoint.client + if err := authorizeClient(client, authConfig, endpoint); err != nil { +- return err ++ return outs, err + } + } + + r, err := NewSession(client, authConfig, endpoint) + if err != nil { +- return err ++ return outs, err + } + + var results *registrytypes.SearchResults +@@ -266,12 +266,12 @@ func (s *DefaultService) searchTerm(term string, limit int, authConfigs map[stri + results, err = r.SearchRepositories(remoteName, limit) + } + if err != nil || results.NumResults < 1 { +- return err ++ return outs, err + } + +- newOuts := make([]registrytypes.SearchResultExt, len(*outs)+len(results.Results)) +- for i := range *outs { +- newOuts[i] = (*outs)[i] ++ newOuts := make([]registrytypes.SearchResultExt, len(outs)+len(results.Results)) ++ for i := range outs { ++ newOuts[i] = (outs)[i] + } + for i, result := range results.Results { + item := registrytypes.SearchResultExt{ +@@ -289,10 +289,10 @@ func (s *DefaultService) searchTerm(term string, limit int, authConfigs map[stri + if newRegistryName != "" { + item.RegistryName, item.Name = newRegistryName, newName + } +- newOuts[len(*outs)+i] = item ++ newOuts[len(outs)+i] = item + } +- *outs = newOuts +- return nil ++ outs = newOuts ++ return outs, nil + } + + // Duplicate entries may occur in result table when omitting index from output because +@@ -341,15 +341,17 @@ func removeSearchDuplicates(data []registrytypes.SearchResultExt) []registrytype + func (s *DefaultService) Search(ctx context.Context, term string, limit int, authConfigs map[string]types.AuthConfig, userAgent string, headers map[string][]string, noIndex bool) ([]registrytypes.SearchResultExt, error) { + results := []registrytypes.SearchResultExt{} + cmpFunc := getSearchResultsCmpFunc(!noIndex) ++ var err error + + // helper for concurrent queries + searchRoutine := func(term string, c chan<- error) { +- err := s.searchTerm(term, limit, authConfigs, userAgent, headers, noIndex, &results) ++ results, err = s.searchTerm(term, limit, authConfigs, userAgent, headers, noIndex, results) + c <- err + } + + if isReposSearchTermFullyQualified(term) { +- if err := s.searchTerm(term, limit, authConfigs, userAgent, headers, noIndex, &results); err != nil { ++ results, err = s.searchTerm(term, limit, authConfigs, userAgent, headers, noIndex, results) ++ if err != nil { + return nil, err + } + } else if len(DefaultRegistries) < 1 { diff --git a/SOURCES/97eff6cf6c9b58f8239b28be2f080e23c9da62c0.patch b/SOURCES/97eff6cf6c9b58f8239b28be2f080e23c9da62c0.patch new file mode 100644 index 0000000..2134937 --- /dev/null +++ b/SOURCES/97eff6cf6c9b58f8239b28be2f080e23c9da62c0.patch @@ -0,0 +1,103 @@ +From 97eff6cf6c9b58f8239b28be2f080e23c9da62c0 Mon Sep 17 00:00:00 2001 +From: Ulrich Obergfell +Date: Thu, 11 Jul 2019 14:33:55 +0200 +Subject: [PATCH] fix deadlock in restore() function + +When containerd starts up, the restore() function walks through the directory +hierarchy under /run/docker/libcontainerd/containerd and imports the state of +processes from files in /run/docker/libcontainerd/containerd/CONTAINERID and +in /run/docker/libcontainerd/containerd/CONTAINERID/PROCESSID. The restore() +function adds an ExitTask entry to the s.tasks queue for each process that is +no longer in state 'running'. The size of the s.tasks queue is hard-coded and +limited to 2048 (defaultBufferSize). If more than 2048 ExitTask entries need +to be added to the queue, the restore() function gets blocked (queue is full). +If this happens, containerd is in a kind of deadlock situation because the +handleTask() function (which would drain the ExitTask entries from the queue) +has not been started in a separate goroutine yet, and the main goroutine is +blocked in the restore() function (unable to start the handleTask() function). + +This patch introduces the dynamically allocated restoreExitTasks slice which +the restore() function uses to store the ExitTask entries separately instead +of adding them to the s.tasks queue. The task handler goroutine subsequently +drains all entries from restoreExitTasks frist before it enters the loop that +handles entries from the s.tasks queue. + +Signed-off-by: Ulrich Obergfell +--- + supervisor/supervisor.go | 35 +++++++++++++++++++++++++++++++++-- + 1 file changed, 33 insertions(+), 2 deletions(-) + +diff --git a/supervisor/supervisor.go b/supervisor/supervisor.go +index 8a26af0..d92de8a 100644 +--- a/supervisor/supervisor.go ++++ b/supervisor/supervisor.go +@@ -18,6 +18,16 @@ const ( + defaultBufferSize = 2048 // size of queue in eventloop + ) + ++// Pointers to all ExitTask that are created by the restore() function are stored in this slice. ++var restoreExitTasks []*ExitTask ++ ++func max(x, y int) int { ++ if x < y { ++ return y ++ } ++ return x ++} ++ + // New returns an initialized Process supervisor. + func New(stateDir string, runtimeName, shimName string, runtimeArgs []string, timeout time.Duration, retainCount int) (*Supervisor, error) { + startTasks := make(chan *startTask, 10) +@@ -207,7 +217,9 @@ type eventV1 struct { + // Events returns an event channel that external consumers can use to receive updates + // on container events + func (s *Supervisor) Events(from time.Time, storedOnly bool, id string) chan Event { +- c := make(chan Event, defaultBufferSize) ++ var c chan Event ++ ++ c = make(chan Event, defaultBufferSize) + if storedOnly { + defer s.Unsubscribe(c) + } +@@ -216,6 +228,9 @@ func (s *Supervisor) Events(from time.Time, storedOnly bool, id string) chan Eve + if !from.IsZero() { + // replay old event + s.eventLock.Lock() ++ close(c) ++ // Allocate a channel that has enough space for the entire event log. ++ c = make(chan Event, max(defaultBufferSize, len(s.eventLog))) + past := s.eventLog[:] + s.eventLock.Unlock() + for _, e := range past { +@@ -276,6 +291,21 @@ func (s *Supervisor) Start() error { + "cpus": s.machine.Cpus, + }).Debug("containerd: supervisor running") + go func() { ++ if (len(restoreExitTasks) > 0) { ++ logrus.Infof("containerd: found %d exited processes after restart", len(restoreExitTasks)) ++ // ++ // If the restore() function stored any ExitTask in the dedicated slice, ++ // then handle those tasks first. The purpose of the one second delay is ++ // to give dockerd a chance to establish its event stream connection to ++ // containerd. If the connection is established before the ExitTask are ++ // being handled, then dockerd can receive exit notifications directly ++ // (rather than having to replay the notifications from the event log). ++ // ++ time.Sleep(time.Second) ++ for _, e := range restoreExitTasks { ++ s.handleTask(e) ++ } ++ } + for i := range s.tasks { + s.handleTask(i) + } +@@ -385,7 +415,8 @@ func (s *Supervisor) restore() error { + Process: p, + } + e.WithContext(context.Background()) +- s.SendTask(e) ++ // Store pointer to ExitTask in dedicated slice. ++ restoreExitTasks = append(restoreExitTasks, e) + } + } + } diff --git a/SOURCES/f9a2eeb64054e740fb1ae3048dde153c257113c8.patch b/SOURCES/f9a2eeb64054e740fb1ae3048dde153c257113c8.patch new file mode 100644 index 0000000..1bd4019 --- /dev/null +++ b/SOURCES/f9a2eeb64054e740fb1ae3048dde153c257113c8.patch @@ -0,0 +1,86 @@ +From f9a2eeb64054e740fb1ae3048dde153c257113c8 Mon Sep 17 00:00:00 2001 +From: Ulrich Obergfell +Date: Thu, 10 Oct 2019 11:16:50 +0200 +Subject: [PATCH] revert changes introduced by "fix error handling in restore() + function", commit e96a10aef66e + (https://github.com/projectatomic/containerd/pull/10) + +Signed-off-by: Ulrich Obergfell +--- + runtime/container.go | 12 ++++++------ + supervisor/supervisor.go | 11 +++-------- + 2 files changed, 9 insertions(+), 14 deletions(-) + +diff --git a/runtime/container.go b/runtime/container.go +index 14002fc..2e9e663 100644 +--- a/runtime/container.go ++++ b/runtime/container.go +@@ -146,15 +146,15 @@ func New(opts ContainerOpts) (Container, error) { + } + + // Load return a new container from the matchin state file on disk. +-func Load(root, id, shimName string, timeout time.Duration) (Container, error, string) { ++func Load(root, id, shimName string, timeout time.Duration) (Container, error) { + var s state + f, err := os.Open(filepath.Join(root, id, StateFile)) + if err != nil { +- return nil, err, "init" ++ return nil, err + } + defer f.Close() + if err := json.NewDecoder(f).Decode(&s); err != nil { +- return nil, err, "init" ++ return nil, err + } + c := &container{ + root: root, +@@ -175,7 +175,7 @@ func Load(root, id, shimName string, timeout time.Duration) (Container, error, s + + dirs, err := ioutil.ReadDir(filepath.Join(root, id)) + if err != nil { +- return nil, err, "init" ++ return nil, err + } + for _, d := range dirs { + if !d.IsDir() { +@@ -184,7 +184,7 @@ func Load(root, id, shimName string, timeout time.Duration) (Container, error, s + pid := d.Name() + s, err := readProcessState(filepath.Join(root, id, pid)) + if err != nil { +- return nil, err, pid ++ return nil, err + } + p, err := loadProcess(filepath.Join(root, id, pid), pid, c, s) + if err != nil { +@@ -193,7 +193,7 @@ func Load(root, id, shimName string, timeout time.Duration) (Container, error, s + } + c.processes[pid] = p + } +- return c, nil, "" ++ return c, nil + } + + func readProcessState(dir string) (*ProcessState, error) { +diff --git a/supervisor/supervisor.go b/supervisor/supervisor.go +index d92de8a..e21ae7b 100644 +--- a/supervisor/supervisor.go ++++ b/supervisor/supervisor.go +@@ -364,15 +364,10 @@ func (s *Supervisor) restore() error { + continue + } + id := d.Name() +- container, err, pid := runtime.Load(s.stateDir, id, s.shim, s.timeout) ++ container, err := runtime.Load(s.stateDir, id, s.shim, s.timeout) + if err != nil { +- if (pid == "init") { +- logrus.WithFields(logrus.Fields{"error": err, "id": id}).Warnf("containerd: failed to load container,removing state directory.") +- os.RemoveAll(filepath.Join(s.stateDir, id)) +- } else { +- logrus.WithFields(logrus.Fields{"error": err, "pid": pid}).Warnf("containerd: failed to load exec process,removing state directory.") +- os.RemoveAll(filepath.Join(s.stateDir, id, pid)) +- } ++ logrus.WithFields(logrus.Fields{"error": err, "id": id}).Warnf("containerd: failed to load container,removing state directory.") ++ os.RemoveAll(filepath.Join(s.stateDir, id)) + continue + } + processes, err := container.Processes() diff --git a/SPECS/docker.spec b/SPECS/docker.spec index 4fa9e1c..1b5c297 100644 --- a/SPECS/docker.spec +++ b/SPECS/docker.spec @@ -56,7 +56,7 @@ # docker-runc %global git_runc https://github.com/projectatomic/runc -%global commit_runc 9c3c5f853ebf0ffac0d087e94daef462133b69c7 +%global commit_runc e45dd70447fb72ee4e1f6989173aa6c5dd492d87 %global shortcommit_runc %(c=%{commit_runc}; echo ${c:0:7}) # docker-containerd @@ -77,7 +77,7 @@ Name: %{repo} Epoch: 2 Version: 1.13.1 -Release: 104.git%{shortcommit_docker}%{?dist} +Release: 108.git%{shortcommit_docker}%{?dist} Summary: Automates deployment of containerized applications License: ASL 2.0 URL: https://%{import_path} @@ -109,6 +109,13 @@ Source29: 99-docker.conf Source30: %{git_tini}/archive/%{commit_tini}/tini-%{shortcommit_tini}.tar.gz Source31: %{git_libnetwork}/archive/%{commit_libnetwork}/libnetwork-%{shortcommit_libnetwork}.tar.gz Source32: seccomp.json +# https://bugzilla.redhat.com/show_bug.cgi?id=1636244 +Patch0: https://github.com/projectatomic/containerd/pull/11/commits/97eff6cf6c9b58f8239b28be2f080e23c9da62c0.patch +# https://bugzilla.redhat.com/show_bug.cgi?id=1653292 +Patch1: https://github.com/projectatomic/containerd/pull/12/commits/f9a2eeb64054e740fb1ae3048dde153c257113c8.patch +Patch2: https://github.com/projectatomic/containerd/pull/12/commits/69518f0bbdb1f11113f46a4d794e09e2f21f5e91.patch +# https://bugzilla.redhat.com/show_bug.cgi?id=1732626 +Patch3: https://github.com/projectatomic/docker/pull/363/commits/6eadd954e5a02f2dcf93928484d42f86b6975618.patch BuildRequires: cmake BuildRequires: sed BuildRequires: git @@ -312,6 +319,13 @@ tar zxf %{SOURCE30} # untar libnetwork tar zxf %{SOURCE31} +cd containerd* +%patch0 -p1 +%patch1 -p1 +%patch2 -p1 +cd - +%patch3 -p1 + %build # compile docker-proxy first - otherwise deps in gopath conflict with the others below and this fails. Remove libnetwork libs then. pushd libnetwork-%{commit_libnetwork} @@ -741,6 +755,24 @@ fi %{_bindir}/%{name}-v1.10-migrator-* %changelog +* Fri Dec 13 2019 Jindrich Novy - 2:1.13.1-108.git4ef4b30 +- bump release to not to clash with RHEL7.8 + +* Fri Dec 13 2019 Jindrich Novy - 2:1.13.1-107.git4ef4b30 +- revert fix for #1766665 as RHEL 7 systemd does not have the CollectMode + property + +* Thu Dec 05 2019 Jindrich Novy - 2:1.13.1-106.git4ef4b30 +- fix "libcontainerd: failed to receive event from containerd:" error (#1636244) +- fix "Pods stuck in terminating state with rpc error: code = 2" (#1653292) +- fix "Docker panics when performing `docker search` due to potential + Search bug when using multiple registries" (#1732626) +- fix race condition in kubelet cgroup destroy process (#1766665) + +* Thu Nov 21 2019 Jindrich Novy - 2:1.13.1-105.git4ef4b30 +- update runc +- Resolves: #1718441 + * Tue Sep 24 2019 Lokesh Mandvekar - 2:1.13.1-104.git4ef4b30 - Resolves: #1653292, #1741718, #1739315, #1733941 - built docker @projectatomic/docker-1.13.1-rhel commit 4ef4b30