-
Notifications
You must be signed in to change notification settings - Fork 18.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Move stdio attach from libcontainerd backend to callback #27467
Conversation
889ee58
to
ea345e5
Compare
👍 for the moving of the logging routine into the container object. |
copyFunc := func(w io.Writer, r io.Reader) { | ||
streamConfig.Add(1) | ||
go func() { | ||
if _, err := io.Copy(w, r); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if we're here it makes sense to use pools.Copy
, because each copy allocates 32Kb regardless of real copy size.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updated
|
||
if err := clnt.backend.AttachStreams(processFriendlyName, *iopipe); err != nil { | ||
clnt.lock(containerID) | ||
if err := attachStdio(*iopipe); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sort of unrelated question, but why don't just use IOPipe
values everywhere to avoid *
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could change that. It's so because it is easier to return nil instead empty struct in openFifos
and I didn't want to pass pointers through pkg boundary when the other side is not meant to change the struct.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks for an explanation, definitely not this PR material
@tonistiigi I'll be happy to give it a spin. Although, given the current lack of a deterministic reproducer, it's hard to say with certainty that any potential fix resolves the issue. Do you have any suggestions for how to make this race happen all the time? |
@ncdc In old code the problem can be reproduced by adding a sleep to https://github.com/docker/docker/blob/668189e7f007dcf276f94453504ee1d7a187ba7f/daemon/monitor.go#L159 . With this patch that part of the code is removed. |
if stdin := streamConfig.Stdin(); stdin != nil { | ||
if iop.Stdin != nil { | ||
go func() { | ||
io.Copy(iop.Stdin, stdin) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should be pools too :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks
LGTM |
@ncdc is this working for you? (at least to your reproducer) |
So far so good. I had my endless loop running for a couple of days and it didn't fail. |
@tonistiigi needs a rebase, ping @mlaventure |
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
LGTM |
I've got a test running and will take a look once I'm at my desk
|
Problem: if a process that's been started for 'docker exec' exits fast enough, the daemon can receive a 'process exited' update from containerd before it starts passing stdio data back and forth, losing its output. Why it happens: the 'process exited' state change message is only processed after acquiring a lock for the container, and while most of the exec() setup is done while holding that lock, the lock is freed when libcontainerd calls back to set up the passing of stdio data. Proposed change: call getExecConfig() before AddProcess(), and modify AddProcess() to take a callback that the daemon can hand it that remembers the exec.Config value that was retrieved. The effect should be the same as that of the changes in moby#27467, but without as much refactoring. Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
Problem: if a process that's been started for 'docker exec' exits fast enough, the daemon can receive a 'process exited' update from containerd before it starts passing stdio data back and forth, losing its output. Why it happens: the 'process exited' state change message is only processed after acquiring a lock for the container, and while most of the exec() setup is done while holding that lock, the lock is freed when libcontainerd calls back to set up the passing of stdio data. Proposed change: call getExecConfig() before AddProcess(), and modify AddProcess() to take a callback that the daemon can hand it that remembers the exec.Config value that was retrieved. The effect should be the same as that of the changes in moby#27467, but without as much refactoring. Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
@tonylambiris That should be a dupe of #27760 |
Thanks for the update. 👍 |
This is cherry-picked from docker upstream PR: moby#27467 Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com> Signed-off-by: Deng Guangxing <dengguangxing@huawei.com>
- Bugfix: Increase udev wait timeout to 185s (mr 365) - Bugfix: Add restarting check before attach a container (mr 362) - Bugfix: daemon: reorder mounts before setting them (mr 350) - Feature: modify centos rpm spec according to that of EulerOS (mr 361) - Backport: fix TestDaemonRestartWithInvalidBasesize (mr 358) - Backport: Ignore "failed to close stdin" if container or process not found (mr 364) - Backport: Reset RemovalInProgress flag on daemon restart (mr 360) - Backport: backport some prs after bumping containerd to v0.2.x branch (mr 342) - Fix restoring behavior when live-restore is not set (moby#24984) - Fix a race in libcontainerd/pausemonitor_linux.go (moby#26695) - Fix libcontainerd: attach streams before create (moby#26744) - add lock in libcontainerd client AddProcess (moby#27094) - Fix issues with fifos blocking on open (moby#27405) - inherit the daemon log options when creating containers (moby#21153) - Fix panic while merging log configs to nil map (moby#24548) - Move stdio attach from libcontainerd backend to callback (moby#27467) - Fix race on sending stdin close event (moby#28682) - Handle paused container when restoring without live-restore set (moby#31704) - Fix daemon panic on restoring containers (moby#25111) Signed-off-by: Lei Jitang <leijitang@huawei.com>
bump to v1.11.2.19 - Bugfix: fix TestDaemonRestartWithInvalidBasesize (mr 358) - Bugfix: Increase udev wait timeout to 185s (mr 365) - Bugfix: Ignore "failed to close stdin" if container or process not found (mr 364) - Bugfix: Add restarting check before attach a container (mr 362) - Feature: modify centos rpm spec according to that of EulerOS (mr 361) - Backport: daemon: reorder mounts before setting them (mr 350) - Backport: Reset RemovalInProgress flag on daemon restart (mr 360) - Backport: backport some prs after bumping containerd to v0.2.x branch (mr 342) - Fix restoring behavior when live-restore is not set (moby#24984) - Fix a race in libcontainerd/pausemonitor_linux.go (moby#26695) - Fix libcontainerd: attach streams before create (moby#26744) - add lock in libcontainerd client AddProcess (moby#27094) - Fix issues with fifos blocking on open (moby#27405) - inherit the daemon log options when creating containers (moby#21153) - Fix panic while merging log configs to nil map (moby#24548) - Move stdio attach from libcontainerd backend to callback (moby#27467) - Fix race on sending stdin close event (moby#28682) - Handle paused container when restoring without live-restore set (moby#31704) - Fix daemon panic on restoring containers (moby#25111) Signed-off-by: Lei Jitang <leijitang@huawei.com> See merge request docker/docker!366
fixes #27289
fixes #27011
Move stdio attaching from backend to callback to fix to keep the lock during startup. Still not very nice because we need to expose public methods because the split between daemon/container/streamconfig is quite arbitrary.
@mlaventure
Signed-off-by: Tonis Tiigi tonistiigi@gmail.com