Skip to content

Commit

Permalink
libpod: fix header length in http attach with logs
Browse files Browse the repository at this point in the history
When we read logs there can be full or partial lines, when it is full we
need to append a newline, thus the message length must be incremented by
one.

Fixes #16856

Signed-off-by: Paul Holzinger <pholzing@redhat.com>
  • Loading branch information
Luap99 committed Dec 16, 2022
1 parent d6c2fa6 commit 6d81441
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 5 deletions.
4 changes: 4 additions & 0 deletions libpod/oci_conmon_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,10 @@ func (r *ConmonOCIRuntime) HTTPAttach(ctr *Container, req *http.Request, w http.
device := logLine.Device
var header []byte
headerLen := uint32(len(logLine.Msg))
if !logLine.Partial() {
// we append and extra newline in this case so we need to increment the len as well
headerLen++
}
logSize += len(logLine.Msg)
switch strings.ToLower(device) {
case "stdin":
Expand Down
5 changes: 3 additions & 2 deletions test/apiv2/20-containers.at
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,10 @@ like "$response_headers" ".*Content-Type: application/json.*" "header does not c
# Regression test for #12904 (race condition in logging code)
mytext="hi-there-$(random_string 15)"
podman run --rm -d --replace --name foo $IMAGE sh -c "echo $mytext;sleep 42"
# Logs output is prepended by ^A^X
# Logs output is prepended by ^A^Y (stdout = 1, length = 25 (with newline))
# Looks like it is missing the required 0 bytes from the message, why?
t POST "containers/foo/attach?logs=true&stream=false" 200 \
$'\001\030'$mytext
$'\001\031'$mytext
t POST "containers/foo/kill" 204

podman run -v /tmp:/tmp $IMAGE true
Expand Down
33 changes: 30 additions & 3 deletions test/apiv2/python/rest_api/test_v2_0_0_container.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,9 +133,36 @@ def test_resize(self):
self.assertEqual(r.text, "", r.text)

def test_attach(self):
self.skipTest("FIXME: Test timeouts")
r = requests.post(self.uri(self.resolve_container("/containers/{}/attach?logs=true")), timeout=5)
self.assertIn(r.status_code, (101, 500), r.text)
r = requests.post(
self.podman_url + "/v1.40/containers/create?name=topcontainer",
json={"Cmd": ["sh", "-c", "echo podman; sleep 100"], "Image": "alpine:latest"},
)
self.assertEqual(r.status_code, 201, r.text)
payload = r.json()

r = requests.post(
self.podman_url
+ f"/v1.40/containers/{payload['Id']}/start"
)
self.assertEqual(r.status_code, 204, r.text)

r = requests.post(
self.podman_url
+ f"/v1.40/containers/{payload['Id']}/attach?logs=true&stream=false"
)
self.assertIn(r.status_code, (101, 200), r.text)
# see the attach format docs, stdout = 1, length = 7, message = podman\n
self.assertEqual(r.content, b"\x01\x00\x00\x00\x00\x00\x00\x07podman\n", r.text)

r = requests.post(
self.podman_url
+ f"/v1.40/containers/{payload['Id']}/stop?t=0"
)
self.assertEqual(r.status_code, 204, r.text)

requests.delete(
self.podman_url + f"/v1.40/containers/{payload['Id']}?force=true"
)

def test_logs(self):
r = requests.get(self.uri(self.resolve_container("/containers/{}/logs?stdout=true")))
Expand Down

0 comments on commit 6d81441

Please sign in to comment.