mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Fix race with containerd events stream on restore
Signed-off-by: Kenfe-Mickael Laventure <mickael.laventure@gmail.com>
This commit is contained in:
parent
643b1c0175
commit
9fff9bb761
1 changed files with 30 additions and 29 deletions
|
@ -405,13 +405,8 @@ func (clnt *client) getContainerLastEventSinceTime(id string, tsp *timestamp.Tim
|
||||||
logrus.Errorf("libcontainerd: failed to get container event for %s: %q", id, err)
|
logrus.Errorf("libcontainerd: failed to get container event for %s: %q", id, err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
ev = e
|
||||||
logrus.Debugf("libcontainerd: received past event %#v", e)
|
logrus.Debugf("libcontainerd: received past event %#v", ev)
|
||||||
|
|
||||||
switch e.Type {
|
|
||||||
case StateExit, StatePause, StateResume:
|
|
||||||
ev = e
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ev, nil
|
return ev, nil
|
||||||
|
@ -456,30 +451,36 @@ func (clnt *client) Restore(containerID string, attachStdio StdioCallback, optio
|
||||||
// Get its last event
|
// Get its last event
|
||||||
ev, eerr := clnt.getContainerLastEvent(containerID)
|
ev, eerr := clnt.getContainerLastEvent(containerID)
|
||||||
if err != nil || cont.Status == "Stopped" {
|
if err != nil || cont.Status == "Stopped" {
|
||||||
if err != nil && !strings.Contains(err.Error(), "container not found") {
|
if err != nil {
|
||||||
// Legitimate error
|
logrus.Warnf("libcontainerd: failed to retrieve container %s state: %v", containerID, err)
|
||||||
return err
|
}
|
||||||
|
if ev != nil && ev.Pid != InitFriendlyName || ev.Type != StateExit {
|
||||||
|
// Wait a while for the exit event
|
||||||
|
timeout := time.NewTimer(10 * time.Second)
|
||||||
|
tick := time.NewTicker(100 * time.Millisecond)
|
||||||
|
stop:
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-timeout.C:
|
||||||
|
break stop
|
||||||
|
case <-tick.C:
|
||||||
|
ev, eerr = clnt.getContainerLastEvent(containerID)
|
||||||
|
if eerr != nil {
|
||||||
|
break stop
|
||||||
|
}
|
||||||
|
if ev != nil && ev.Pid == InitFriendlyName && ev.Type == StateExit {
|
||||||
|
break stop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
timeout.Stop()
|
||||||
|
tick.Stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
if ev == nil {
|
// get the exit status for this container, if we don't have
|
||||||
if _, err := clnt.getContainer(containerID); err == nil {
|
// one, indicate an error
|
||||||
// If ev is nil and the container is running in containerd,
|
ec := uint32(255)
|
||||||
// we already consumed all the event of the
|
if eerr == nil && ev != nil && ev.Pid == InitFriendlyName && ev.Type == StateExit {
|
||||||
// container, included the "exit" one.
|
|
||||||
// Thus we return to avoid overriding the Exit Code.
|
|
||||||
logrus.Warnf("libcontainerd: restore was called on a fully synced container (%s)", containerID)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
// the container is not running so we need to fix the state within docker
|
|
||||||
ev = &containerd.Event{
|
|
||||||
Type: StateExit,
|
|
||||||
Status: 1,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the exit status for this container
|
|
||||||
ec := uint32(0)
|
|
||||||
if eerr == nil && ev.Type == StateExit {
|
|
||||||
ec = ev.Status
|
ec = ev.Status
|
||||||
}
|
}
|
||||||
clnt.setExited(containerID, ec)
|
clnt.setExited(containerID, ec)
|
||||||
|
|
Loading…
Add table
Reference in a new issue