Skip to content

Commit 844f3ed

Browse files
committed
fix(attach): resolve exec startup-size race and non-blocking resize sends
1 parent d3269ce commit 844f3ed

2 files changed

Lines changed: 28 additions & 6 deletions

File tree

internal/cmd/attach.go

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -348,9 +348,15 @@ func attachExec(ctx context.Context, client *docker.Client, dir string, session
348348
defer close(sigDone)
349349
for {
350350
select {
351-
case <-sigCh:
352-
if w, h, err := term.GetSize(fd); err == nil {
353-
resizeCh <- docker.TerminalSize{Width: uint(w), Height: uint(h)} //nolint:gosec // terminal dimensions are always positive
351+
case <-sigCh:
352+
if w, h, err := term.GetSize(fd); err == nil {
353+
size := docker.TerminalSize{Width: uint(w), Height: uint(h)} //nolint:gosec // terminal dimensions are always positive
354+
select {
355+
case resizeCh <- size:
356+
default:
357+
<-resizeCh
358+
resizeCh <- size
359+
}
354360
}
355361
case <-ctx.Done():
356362
return
@@ -373,9 +379,15 @@ func attachExec(ctx context.Context, client *docker.Client, dir string, session
373379
defer ticker.Stop()
374380
for {
375381
select {
376-
case <-ticker.C:
377-
if w, h, err := term.GetSize(fd); err == nil && (w != lastW || h != lastH) {
378-
resizeCh <- docker.TerminalSize{Width: uint(w), Height: uint(h)} //nolint:gosec // terminal dimensions are always positive
382+
case <-ticker.C:
383+
if w, h, err := term.GetSize(fd); err == nil && (w != lastW || h != lastH) {
384+
size := docker.TerminalSize{Width: uint(w), Height: uint(h)} //nolint:gosec // terminal dimensions are always positive
385+
select {
386+
case resizeCh <- size:
387+
default:
388+
<-resizeCh
389+
resizeCh <- size
390+
}
379391
lastW, lastH = w, h
380392
}
381393
case <-ctx.Done():

internal/docker/docker.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,16 @@ func (c *Client) ExecInteractive(ctx context.Context, containerID string, args [
334334
Tty: true,
335335
}
336336

337+
// Apply initial terminal size before starting the exec so the process
338+
// launches with the correct dimensions (avoids startup-size race).
339+
if resizeCh != nil {
340+
select {
341+
case size := <-resizeCh:
342+
execCfg.ConsoleSize = &[2]uint{size.Height, size.Width}
343+
default:
344+
}
345+
}
346+
337347
execResp, err := engineCli.ContainerExecCreate(ctx, containerID, execCfg)
338348
if err != nil {
339349
return fmt.Errorf("create exec in container %s: %w", containerID, err)

0 commit comments

Comments
 (0)