Skip to content

archive: fix race condition in cmdStream#39860

Merged
cpuguy83 merged 1 commit intomoby:masterfrom
stbenjam:cmd-race
Sep 12, 2019
Merged

archive: fix race condition in cmdStream#39860
cpuguy83 merged 1 commit intomoby:masterfrom
stbenjam:cmd-race

Conversation

@stbenjam
Copy link
Contributor

@stbenjam stbenjam commented Sep 3, 2019

- What I did

Fixed a race condition, see details in issue #39859

- How I did it

Ensured that cmd.Wait is done, before any clean up happens.

- How to verify it

There is a reproducer at https://github.com/stbenjam/docker-race-reproducer. Run the code as-is, and then apply the changes in this PR to vendor/github.com/docker/docker/pkg/archive/archive.go. You'll see the issue is fixed.

- Description for the changelog

Fixed a race condition in cmdStream to ensure that we wait for the command to exit before any clean up.

- A picture of a cute animal (not mandatory but encouraged)

My dog, Tilly:

dogTilly

@GordonTheTurtle GordonTheTurtle added the dco/no Automatically set by a bot when one of the commits lacks proper signature label Sep 3, 2019
@GordonTheTurtle
Copy link

Please sign your commits following these rules:
https://github.com/moby/moby/blob/master/CONTRIBUTING.md#sign-your-work
The easiest way to do this is to amend the last commit:

$ git clone -b "cmd-race" [email protected]:stbenjam/moby.git somewhere
$ cd somewhere
$ git commit --amend -s --no-edit
$ git push -f

Amending updates the existing PR. You DO NOT need to open a new one.

@thaJeztah
Copy link
Member

ping @kolyshkin @tiborvass PTAL

@tiborvass
Copy link
Contributor

Another way to find the race is to run go test -race ./pkg/archive. We could/should run unit tests with -race as well.

There is a race condition in pkg/archive when using `cmd.Start` for pigz
and xz where the `*bufio.Reader` could be returned to the pool while the
command is still writing to it, and then picked up and used by a new
command.

The command is wrapped in a `CommandContext` where the process will be
killed when the context is cancelled, however this is not instantaneous,
so there's a brief window while the command is still running but the
`*bufio.Reader` was already returned to the pool.

wrapReadCloser calls `cancel()`, and then `readBuf.Close()` which
eventually returns the buffer to the pool. However, because cmdStream
runs `cmd.Wait` in a go routine that we never wait for to finish, it is
not safe to return the reader to the pool yet.  We need to ensure we
wait for `cmd.Wait` to finish!

Signed-off-by: Stephen Benjamin <[email protected]>
@thaJeztah
Copy link
Member

@tiborvass @kolyshkin PR was updated; PTAL

Copy link
Contributor

@kolyshkin kolyshkin left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Member

@cpuguy83 cpuguy83 left a comment

Choose a reason for hiding this comment

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

LGTM

@tiborvass
Copy link
Contributor

FYI a followup to this PR is in #39920

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants