Skip to content
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

Fix a potential race around the exec cleanup process #13600

Merged
merged 1 commit into from
Mar 23, 2022

Conversation

mheon
Copy link
Member

@mheon mheon commented Mar 22, 2022

Every exec session run attached will, on exit, do two things: it will signal the associated podman exec that it is finished (to allow Podman to collect the exit code and exit), and spawn a cleanup process to clean up the exec session (in case the podman exec process died, we still need to clean up). If an exec session is created that exits almost instantly, but generates a large amount of output (e.g. prints thousands of lines), the cleanup process can potentially execute before podman exec has a chance to read the exit code, resulting in errors. Handle this by detecting if the cleanup process has already removed the exec session before handling the error from reading the exec exit code.

[NO NEW TESTS NEEDED] I have no idea how to test this in CI.

Fixes #13227

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Mar 22, 2022

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: mheon

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-ci openshift-ci bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Mar 22, 2022
@mheon mheon force-pushed the exec_cleanup_race branch from 2154093 to b8cf48a Compare March 22, 2022 18:44
// If we can't do this, no point in continuing, any attempt to save
// would write garbage to the DB.
if err := c.syncContainer(); err != nil {
if errors.Cause(err) == define.ErrNoSuchCtr || errors.Cause(err) == define.ErrCtrRemoved {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please start using errors.Is for new code


logrus.Debugf("Container %s exec session %s completed with exit code %d", c.ID(), session.ID(), exitCode)
if newSess.State == define.ExecStateStopped && os.IsNotExist(exitCodeErr) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here use errors.Is instead of os.IsNotExist

@mheon
Copy link
Member Author

mheon commented Mar 22, 2022

Adding WIP this isn't doing what I expect

@mheon mheon changed the title Fix a potential race around the exec cleanup process WIP: Fix a potential race around the exec cleanup process Mar 22, 2022
@openshift-ci openshift-ci bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Mar 22, 2022
@mheon
Copy link
Member Author

mheon commented Mar 22, 2022

I think I fixed it, going to repush

@mheon mheon force-pushed the exec_cleanup_race branch from b8cf48a to 72bba5c Compare March 22, 2022 19:23
@mheon mheon changed the title WIP: Fix a potential race around the exec cleanup process Fix a potential race around the exec cleanup process Mar 22, 2022
@openshift-ci openshift-ci bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Mar 22, 2022
@mheon mheon force-pushed the exec_cleanup_race branch from 72bba5c to 111ed2f Compare March 22, 2022 19:23
@mheon
Copy link
Member Author

mheon commented Mar 22, 2022

@edsantiago PTAL, I have this running on a 1MT and it seems to be running through the reproducer without issue.

@edsantiago
Copy link
Member

@thrix FYI

Copy link
Member

@edsantiago edsantiago left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no way I can review the locking flow; and I shudder at the thought of building this in a CentOS container. I'll trust your testing. Two very minor comments.


// Lock again.
// Important: we must lock and sync *before* the above error is handled.
// We need into from the database to handle the error.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm guessing that's a typo for "info"?

Comment on lines 359 to 361
// Container's entirely removed. We can't save status,
// but the container's entirely removed, so we don't
// need to. Exit without error.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Repetitive comment; maybe clearer as "Container is entirely removed, so there's no need to save status. Exit without error."

@mheon mheon force-pushed the exec_cleanup_race branch from 111ed2f to 780f448 Compare March 22, 2022 20:16
@mheon
Copy link
Member Author

mheon commented Mar 22, 2022

@containers/podman-maintainers PTAL

@giuseppe
Copy link
Member

If an exec session is created that exits almost instantly, but generates a large amount of output (e.g. prints thousands of lines), the cleanup process can potentially execute before podman exec has a chance to read the exit code, resulting in errors.

is it a race in conmon? I don' think it should call the cleanup process before reading all the container output and writing the exit code

@mheon
Copy link
Member Author

mheon commented Mar 23, 2022

@giuseppe I don't think so? My suspicion is this: Conmon sends all the output (a considerable amount, probably 10kb?) over the unix socket to Podman, detects that the container has exited (it does so almost instantly), and spawns the cleanup process. Podman, meanwhile, is still reading the container's output from the Unix socket and writing it to the terminal - which, per Ed's experimentation, seems to be the limiting factor (is writing to TTYs rate-limited in some way? I should look into this) and takes more time than it does for Conmon to finish sending output, write the exit file, and invoke the cleanup process. The cleanup process wakes up and runs in the background, reads (and removes) the exit file, and writes the exit code to the DB. Podman presumably finishes writing sometime during this, but the container lock forces it to wait until after the cleanup process is finished; by which point there was no exit file, hence error messages.

Every exec session run attached will, on exit, do two things: it
will signal the associated `podman exec` that it is finished (to
allow Podman to collect the exit code and exit), and spawn a
cleanup process to clean up the exec session (in case the `podman
exec` process died, we still need to clean up). If an exec
session is created that exits almost instantly, but generates a
large amount of output (e.g. prints thousands of lines), the
cleanup process can potentially execute before `podman exec` has
a chance to read the exit code, resulting in errors. Handle this
by detecting if the cleanup process has already removed the exec
session before handling the error from reading the exec exit
code.

[NO NEW TESTS NEEDED] I have no idea how to test this in CI.

Fixes containers#13227

Signed-off-by: Matthew Heon <[email protected]>
@mheon mheon force-pushed the exec_cleanup_race branch from 780f448 to 5b2597d Compare March 23, 2022 13:33
@mheon
Copy link
Member Author

mheon commented Mar 23, 2022

Can we merge this, or are there further questions?

@mheon
Copy link
Member Author

mheon commented Mar 23, 2022

@baude @Luap99 @vrothberg PTAL

@rhatdan
Copy link
Member

rhatdan commented Mar 23, 2022

LGTM

@baude
Copy link
Member

baude commented Mar 23, 2022

/lgtm

@openshift-ci openshift-ci bot added the lgtm Indicates that a PR is ready to be merged. label Mar 23, 2022
@openshift-merge-robot openshift-merge-robot merged commit a1e2897 into containers:main Mar 23, 2022
@github-actions github-actions bot added the locked - please file new issue/PR Assist humans wanting to comment on an old issue or PR with locked comments. label Sep 21, 2023
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Sep 21, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. lgtm Indicates that a PR is ready to be merged. locked - please file new issue/PR Assist humans wanting to comment on an old issue or PR with locked comments.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

podman-in-podman: Error: timed out waiting for file: internal libpod error
9 participants