Skip to content

Implement exec kill API#38704

Closed
dtaniwaki wants to merge 1 commit intomoby:masterfrom
dtaniwaki:35703-exec-kill
Closed

Implement exec kill API#38704
dtaniwaki wants to merge 1 commit intomoby:masterfrom
dtaniwaki:35703-exec-kill

Conversation

@dtaniwaki
Copy link
Copy Markdown

@dtaniwaki dtaniwaki commented Feb 10, 2019

Closes #35703 #9098

- What I did

I implemented a feature to kill exec instance.

- How I did it

I added an API endpoint for the action and a method to call it in the client, then implemented an exec action in the daemon.

- How to verify it

  • Run sleep container by docker run --name exec-kill -d ubuntu:16.04 sleep infinity
  • Then, attach a process by docker exec -d exec-kill sleep 99999. (use different sleep time from the container command to easily identify it)
  • Now, you can see the executed process by executing ps aux.
  • You can get the exec ID by docker inspect exec-kill | grep ExecIDs -A 3.
  • Then kill the exec instance by curl --unix-socket /var/run/docker.sock -X DELETE "http:/v1.40/exec/<EXEC_ID>".
  • Check if the executed process is gone by ps aux.

- Description for the changelog

Add exec kill feature with API endpoint and a client method

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

268878_2231235108554_8050336_n

@GordonTheTurtle
Copy link
Copy Markdown

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 "35703-exec-kill" git@github.com:dtaniwaki/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.

@GordonTheTurtle GordonTheTurtle added dco/no Automatically set by a bot when one of the commits lacks proper signature status/0-triage labels Feb 10, 2019
@GordonTheTurtle GordonTheTurtle removed the dco/no Automatically set by a bot when one of the commits lacks proper signature label Feb 10, 2019
Copy link
Copy Markdown
Member

@AkihiroSuda AkihiroSuda left a comment

Choose a reason for hiding this comment

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

Design looks good. Thank you

@dtaniwaki dtaniwaki force-pushed the 35703-exec-kill branch 2 times, most recently from 69439f2 to 880c309 Compare February 11, 2019 03:57
@dtaniwaki
Copy link
Copy Markdown
Author

@AkihiroSuda Thank you for reviewing my pull request. I updated the code based on your review result. Would you check it again?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

why?

Copy link
Copy Markdown
Author

@dtaniwaki dtaniwaki Feb 11, 2019

Choose a reason for hiding this comment

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

I'd like to have your opinion about the behavior of the exec kill feature.

Currently, it just sends a signal to the process and doesn't remove the instance from execCommands. That's why I assumed it might not finish just after calling the method. If we want to make the kill action with a synchronized manner, we have to wait for the process termination in ContainerExecKill to remove the exec instance, but it requires timeout in its option. On the other hand, if we remove the exec instance just after sending a signal to the process, we can make it synchronized easily without timeout, but have the possibility of resource leakage.

Which do you think is better?

Copy link
Copy Markdown
Author

@dtaniwaki dtaniwaki Feb 11, 2019

Choose a reason for hiding this comment

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

To consider non-force cases (TERM signal), I think ContainerExecKill should just send a signal to the running process and the caller should take care of the result just like the kill command of Linux.

@dtaniwaki dtaniwaki force-pushed the 35703-exec-kill branch 2 times, most recently from 8830e2b to 0e55615 Compare February 11, 2019 06:03
@codecov
Copy link
Copy Markdown

codecov bot commented Feb 11, 2019

Codecov Report

Merging #38704 into master will increase coverage by 0.03%.
The diff coverage is 64.7%.

@@            Coverage Diff             @@
##           master   #38704      +/-   ##
==========================================
+ Coverage   36.53%   36.57%   +0.03%     
==========================================
  Files         610      610              
  Lines       45395    45410      +15     
==========================================
+ Hits        16584    16607      +23     
+ Misses      26517    26506      -11     
- Partials     2294     2297       +3

@dtaniwaki
Copy link
Copy Markdown
Author

dtaniwaki commented Feb 11, 2019

I think the error of janky and experimental is not related to my change.

17:20:11 OOPS: 1472 passed, 51 skipped, 1 FAILED
17:20:11 --- FAIL: Test (5541.25s)
17:20:11 FAIL
17:20:11 ---> Making bundle: .integration-daemon-stop (in bundles/test-integration)

@GordonTheTurtle GordonTheTurtle added dco/no Automatically set by a bot when one of the commits lacks proper signature and removed rebuild/experimental labels Feb 11, 2019
@GordonTheTurtle GordonTheTurtle removed the dco/no Automatically set by a bot when one of the commits lacks proper signature label Feb 12, 2019
@dtaniwaki
Copy link
Copy Markdown
Author

I added a test for daemon so it doesn't decrease the coverage by codecov.

Copy link
Copy Markdown
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.

This endpoint should really match the container kill endpoint (POST) and accept a kill signal.

@dtaniwaki
Copy link
Copy Markdown
Author

dtaniwaki commented Feb 13, 2019

Hmm... It's weird. The test passes in my local and the error in CI

09:44:53 # github.com/docker/docker/daemon [github.com/docker/docker/daemon.test]
09:44:53 daemon\exec_test.go:15:2: undefined: MockContainerdClient
09:44:54 FAIL	github.com/docker/docker/daemon [build failed]

should not happen.

@dtaniwaki
Copy link
Copy Markdown
Author

@cpuguy83 The error windows CI failed with is weird. The same composition exists in resize test of daemon. Could you tell me possible reason of this failure?

@AkihiroSuda
Copy link
Copy Markdown
Member

@dtaniwaki MockContainerdClient is only compiled for Linux

// +build linux

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

how can this happen

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

The state of a process is checked periodically just below this line. I'd like to make sure if it's running.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

IIUC case <-ticker.C: is always executed after 1sec? Then case <-time.After(5 * time.Second): won't be executed?

Copy link
Copy Markdown
Author

@dtaniwaki dtaniwaki Feb 13, 2019

Choose a reason for hiding this comment

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

Yes, that's true. However, I put the safety guard just in case if it doesn't finish in a few seconds. I'll remove it and put a sleep of 1 second instead if it's better.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Please refer to

var (
waitCh = make(chan struct{})
resCh = make(chan struct {
content string
err error
})
)
go func() {
close(waitCh)
defer close(resCh)
r, err := ioutil.ReadAll(resp.Reader)
resCh <- struct {
content string
err error
}{
content: string(r),
err: err,
}
}()
<-waitCh
select {
case <-time.After(3 * time.Second):
t.Fatal("failed to read the content in time")
case got := <-resCh:
assert.NilError(t, got.err)
// NOTE: using Contains because no-tty's stream contains UX information
// like size, stream type.
assert.Assert(t, is.Contains(got.content, expected))
}

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I think the code you mentioned is to wait for closed connection which can block until disconnection. The test I wrote uses detach option in ContainerExecCreate, and ContainerExecInspect may return not found error or a response with Running=false without blocking. Could you tell me how to wait for an active exec instance in more detail?

@dtaniwaki dtaniwaki force-pushed the 35703-exec-kill branch 2 times, most recently from ce4cb29 to 342d072 Compare February 13, 2019 13:23
Signed-off-by: Daisuke Taniwaki <daisuketaniwaki@gmail.com>
@cpuguy83
Copy link
Copy Markdown
Member

Windows does not use containerd.

@awesomebytes
Copy link
Copy Markdown

Will this PR be re-reviewed at some point? It would be great to have it. It would allow to make docker exec more of a first class citizen like docker run and either avoid or ease the workaround I needed to create to ensure that processes spawned by docker exec die when docker exec dies: #9098 (comment)

@AkihiroSuda
Copy link
Copy Markdown
Member

needs rebase

@awesomebytes
Copy link
Copy Markdown

@AkihiroSuda I've given a shot to try to rebase it here: #41548

I pre-apologize if it just explodes in the CI, I've never used Go before, neither I knew how to build the project to test it.

@AkihiroSuda
Copy link
Copy Markdown
Member

Thanks @awesomebytes

I've never used Go before, neither I knew how to build the project to test it.

Testing Moby is quite different from other Go programs; the test scripts can be locally executed by running make test-integration
https://github.com/moby/moby/blob/master/docs/contributing/test.md

@awesomebytes
Copy link
Copy Markdown

Thanks for the link @AkihiroSuda I'll try to fix things locally before further spamming your CI system.

@dtaniwaki
Copy link
Copy Markdown
Author

I'm closing this PR as the implementation is taken over to #41548 thanks to @awesomebytes and @adamjseitz.

@dtaniwaki dtaniwaki closed this Jul 20, 2021
@dtaniwaki dtaniwaki deleted the 35703-exec-kill branch July 20, 2021 05:10
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.

introduce docker exec kill

7 participants