mirror of
https://github.com/containers/podman.git
synced 2025-09-15 12:48:58 +08:00

There is race condition in the remote client attach logic. Because the resize api call was handled in an extra goroutine the container was started before the resize call happend. To fix this we have to call resize in the same goroutine as attach. When the first resize is done start a goroutine to listen on SIGWINCH in the background and resize again if the signal is received. Fixes #9859 Signed-off-by: Paul Holzinger <pholzing@redhat.com>
87 lines
2.5 KiB
Go
87 lines
2.5 KiB
Go
package compat
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"strings"
|
|
|
|
"github.com/containers/podman/v3/libpod"
|
|
"github.com/containers/podman/v3/libpod/define"
|
|
"github.com/containers/podman/v3/pkg/api/handlers/utils"
|
|
"github.com/gorilla/mux"
|
|
"github.com/gorilla/schema"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
func ResizeTTY(w http.ResponseWriter, r *http.Request) {
|
|
runtime := r.Context().Value("runtime").(*libpod.Runtime)
|
|
decoder := r.Context().Value("decoder").(*schema.Decoder)
|
|
|
|
// /containers/{id}/resize
|
|
query := struct {
|
|
Height uint16 `schema:"h"`
|
|
Width uint16 `schema:"w"`
|
|
IgnoreNotRunning bool `schema:"running"`
|
|
}{
|
|
// override any golang type defaults
|
|
}
|
|
|
|
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
|
|
utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
|
|
errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
|
|
return
|
|
}
|
|
|
|
sz := define.TerminalSize{
|
|
Width: query.Width,
|
|
Height: query.Height,
|
|
}
|
|
|
|
var status int
|
|
switch {
|
|
case strings.Contains(r.URL.Path, "/containers/"):
|
|
name := utils.GetName(r)
|
|
ctnr, err := runtime.LookupContainer(name)
|
|
if err != nil {
|
|
utils.ContainerNotFound(w, name, err)
|
|
return
|
|
}
|
|
if err := ctnr.AttachResize(sz); err != nil {
|
|
if errors.Cause(err) != define.ErrCtrStateInvalid {
|
|
utils.InternalServerError(w, errors.Wrapf(err, "cannot resize container"))
|
|
} else {
|
|
utils.Error(w, "Container not running", http.StatusConflict, err)
|
|
}
|
|
return
|
|
}
|
|
// This is not a 204, even though we write nothing, for compatibility
|
|
// reasons.
|
|
status = http.StatusOK
|
|
case strings.Contains(r.URL.Path, "/exec/"):
|
|
name := mux.Vars(r)["id"]
|
|
ctnr, err := runtime.GetExecSessionContainer(name)
|
|
if err != nil {
|
|
utils.SessionNotFound(w, name, err)
|
|
return
|
|
}
|
|
if state, err := ctnr.State(); err != nil {
|
|
utils.InternalServerError(w, errors.Wrapf(err, "cannot obtain session container state"))
|
|
return
|
|
} else if state != define.ContainerStateRunning && !query.IgnoreNotRunning {
|
|
utils.Error(w, "Container not running", http.StatusConflict,
|
|
fmt.Errorf("container %q in wrong state %q", name, state.String()))
|
|
return
|
|
}
|
|
if err := ctnr.ExecResize(name, sz); err != nil {
|
|
if errors.Cause(err) != define.ErrCtrStateInvalid || !query.IgnoreNotRunning {
|
|
utils.InternalServerError(w, errors.Wrapf(err, "cannot resize session"))
|
|
return
|
|
}
|
|
}
|
|
// This is not a 204, even though we write nothing, for compatibility
|
|
// reasons.
|
|
status = http.StatusCreated
|
|
}
|
|
w.WriteHeader(status)
|
|
}
|