-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
investigate terminal resize issues, and (if possible) set size on creation #3554
Comments
Just a quick comment, if I change the amount of sleep between two resizes to 200ms then the error goes away completely for me, this is obviously not ideal and makes me think that this is more an error on the daemon side, I'll continue looking. |
200ms seems quite long to wait between tries; so seems to indicate something has become "slower" 🤔 was the 200ms just a "let's try something bigger", or did you try incrementing in smaller steps? (perhaps we can do a quick try to see where the "it mostly works" threshold is). For a short term "quick fix", we could increase the timeout (although I hope if doesn't have to be 200ms!!!); of course the ideal solution is to (as described above) look if we can set the correct size when creating (so that we don't have to do the resize loop); of course if we do, that likely would have to be done only on "newer" APIs only (would have to check); and of course if dockerd and containerd actually support it (and if not "why not?") |
We could either do 200ms, or 100ms but retry 10 times, it looks like 1 second is the lowest we should go, see this comment by @cpuguy83 I did a quick check and it seems that you can set the TTY when you create a container, here is the test: containerd code to set TTY size on creationpackage main
import (
"context"
"errors"
"fmt"
"log"
"syscall"
"time"
"github.com/containerd/console"
"github.com/containerd/containerd"
"github.com/containerd/containerd/cio"
"github.com/containerd/containerd/namespaces"
"github.com/containerd/containerd/oci"
)
func main() {
if err := redisExample(); err != nil {
log.Fatal(err)
}
}
func redisExample() error {
// create a new client connected to the default socket path for containerd
client, err := containerd.New("/run/containerd/containerd.sock")
if err != nil {
return err
}
defer client.Close()
// create a new context with an "example" namespace
ctx := namespaces.WithNamespace(context.Background(), "example")
// pull the redis image from DockerHub
image, err := client.Pull(ctx, "docker.io/library/busybox:latest", containerd.WithPullUnpack)
if err != nil {
return err
}
// create a container
container, err := client.NewContainer(
ctx,
"redis-server",
containerd.WithImage(image),
containerd.WithNewSnapshot("redis-server-snapshot", image),
// Setting a small size terminal to make sure this is taken into account, to test run "ls", it should wrap
// its output to fit into a small window
containerd.WithNewSpec(oci.Compose(oci.WithImageConfig(image), oci.WithTTY, oci.WithTTYSize(30, 30))),
)
if err != nil {
return err
}
defer container.Delete(ctx, containerd.WithSnapshotCleanup)
var con console.Console
con = console.Current()
defer con.Reset()
if err := con.SetRaw(); err != nil {
return fmt.Errorf("failed to SetRaw,err is: %w", err)
}
if con == nil {
return errors.New("got nil con with flagT=true")
}
// create a task from the container
task, err := container.NewTask(ctx, cio.NewCreator(cio.WithStreams(con, con, nil), cio.WithTerminal))
if err != nil {
return err
}
defer task.Delete(ctx)
// make sure we wait before calling start
exitStatusC, err := task.Wait(ctx)
if err != nil {
fmt.Println(err)
}
// call start on the task to execute the redis server
if err := task.Start(ctx); err != nil {
return err
}
// sleep for a lil bit to see the logs
time.Sleep(30 * time.Second)
// kill the process and get the exit status
if err := task.Kill(ctx, syscall.SIGTERM); err != nil {
return err
}
// wait for the process to fully exit and print out the exit status
status := <-exitStatusC
code, _, err := status.Result()
if err != nil {
return err
}
fmt.Printf("redis-server exited with status: %d\n", code)
return nil
} Running this code doesn't fail and the terminal size is right: ➜ containerdtest sudo ./containerdtest
/ # ls
bin home run usr
dev proc sys var
etc root tmp |
That's odd, works on my machine :D |
you on Safari, or on Chrome? (looks indeed to still work on Chrome 🤔) |
I'm on Firefox and yeah, it works well |
I some cases, for example if there is a heavy load, the initialization of the TTY size would fail. This change makes the cli retry more times, 10 instead of 5 and we wait 100ms between two calls to resize the TTY. Relates to docker#3554 Signed-off-by: Djordje Lukic <[email protected]>
I some cases, for example if there is a heavy load, the initialization of the TTY size would fail. This change makes the cli retry more times, 10 instead of 5 and we wait 100ms between two calls to resize the TTY. Relates to docker#3554 Signed-off-by: Djordje Lukic <[email protected]>
I some cases, for example if there is a heavy load, the initialization of the TTY size would fail. This change makes the cli retry more times, 10 instead of 5 and we wait 100ms between two calls to resize the TTY. Relates to docker#3554 Signed-off-by: Djordje Lukic <[email protected]>
Arf; didn't post 😂 Back to "on topic"; with your test, could you try if it picks up the size immediately? (I recall the issue when not resizing is that everything "seems" ok, only to discover the size is limited to the default 80-chars, and output getting truncated. For example; On my host; tput cols && tput lines
204
37 And in a container: docker run -it --rm ubuntu sh -c 'tput cols; tput lines'
80
24 (this is with the current release, so the initial size is still |
Tested with my code above, I changed the image to be ubuntu and added |
Nice. so perhaps "all" that would be needed are the changes I mentioned in #3572 (comment) applying the changes in Moby isn't too difficult (but as described there, the "expectations" on the client side will have to be gated by API version (pre v1.42 -> do the resize loop, API v1.42 or up -> initial size should already be good) |
Updating this thread; this PR is making the time between retries a bit longer, and changes the logic for the initial resize to try 10 times (instead of 5); Copying my comment (#3573 (comment)) from that PR so that it doesn't get lost once that's merged;
|
I some cases, for example if there is a heavy load, the initialization of the TTY size would fail. This change makes the cli retry 10 times instead of 5 and we wait incrementally from 10ms to 100ms Relates to docker#3554 Signed-off-by: Djordje Lukic <[email protected]>
I some cases, for example if there is a heavy load, the initialization of the TTY size would fail. This change makes the cli retry 10 times instead of 5 and we wait incrementally from 10ms to 100ms Relates to docker#3554 Signed-off-by: Djordje Lukic <[email protected]>
I some cases, for example if there is a heavy load, the initialization of the TTY size would fail. This change makes the cli retry 10 times instead of 5 and we wait incrementally from 10ms to 100ms Relates to docker#3554 Signed-off-by: Djordje Lukic <[email protected]>
So fixes are being made in moby/moby#43593 and #3619 was merged, which also sets the size on Let me copy my comment from a Slack thread with @vvoland I was digging a bit in the code, and wondering if we could also make it work for p, err = t.Exec(ctx, processID, spec, func(id string) (cio.IO, error) {
rio, err = c.createIO(fifos, containerID, processID, stdinCloseSync, attachStdio)
return rio, err
}) In which So if I'm right, it would be possible to have |
…inate terminal size problems (and other strange docker bugs related to display). See docker/cli#3554
Is this fully fixed now in v23? moby/moby#43622 and #3627 seem to address the recent comment. |
I think it may be yes; @vvoland was there anything left to look into? |
No, this was fully addressed as far as I know, so I think this can be closed. @markdascher are you still experiencing any of the issues described here? |
I think my issues were gone after the initial fixes somewhere around v18, so I'm probably not the best judge. (But for what it's worth, I haven't seen any issues with recent versions.) Mostly I was just poking around to see when all the remaining edge cases would've been fixed, and the answer seems to be v23. But then saw this issue was still open. |
Alright; looks like it's time to close this one then! Thanks for the reminder 🤗 |
…inate terminal size problems (and other strange docker bugs related to display). See docker/cli#3554
relates to:
The
TestInitTtySizeErrors
test is failing frequently (see #3441), and it looks like it's not just a flaky test, but a bug / regression in the CLI:We had issues in this area before;
Previous "fixes" implemented a retry loop to try resizing the terminal if it didn't work the first time (there's some race between the container being created and it being receptacle for resizing), so the existing code continues to be a "best effort";
cli/cli/command/container/run.go
Lines 189 to 193 in b68db38
Reproduction steps
The issue can be reproduced with this script (which just starts a lot of containers in a loop); I haven't counted the success/failure ratio, but it's failing very frequently:
Coincidentally, when using a Windows machine, the CLI sets the initial size when creating the container.
cli/cli/command/container/run.go
Lines 122 to 127 in b68db38
The code above looks wrong though;
What's needed?
docker run
), attaching (docker attach
) and exec-ing (docker exec
) a containerIf it's possible to set the initial size, we should prefer that over "resizing", although resizing would still be needed if the terminal from which the container was started is resized. Of course, we also need to take into account whether the daemon (and containerd) supports setting the initial size (which may depend on the API version).
The text was updated successfully, but these errors were encountered: