Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@sameo
Copy link

@sameo sameo commented Jan 11, 2017

Some OCI container runtimes (in particular the hypervisor based ones like e.g. Clear Containers) will typically create a shim process between the hypervisor and the runtime caller, in order to not rely on the hypervisor process for e.g. forwarding the output streams or getting a command exit code.

When executing a command inside a running container those runtimes will create that shim process and terminate.
Therefore calling and monitoring the runtime process directly from ExecSync() will fail. Instead we need to have a subreaper calling the runtime and monitoring the shim process, and conmon seems to be a natural place for doing so.

This PR does mostly 2 things:

  1. Add a -e option to conmon to also monitor potential shim processes created by <runtime> exec
  2. Modify ExecSync to call conmon instead of calling the runtime directly. ExecSync also now reads the exit status code back through the synchronization pipe.

Fixes #309

@sameo sameo force-pushed the topic/cc-exec branch 2 times, most recently from 391b70f to 9fd2477 Compare January 11, 2017 09:52
@runcom
Copy link
Member

runcom commented Jan 11, 2017

I'm overall ok to have conmon exec, @mrunalp @cyphar PTAL

run ocic ctr execsync --id "$ctr_id" doesnotexist
echo "$output"
[ "$status" -ne 0 ]
[[ "$output" =~ "executable file not found in" ]]
Copy link
Member

Choose a reason for hiding this comment

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

Where has this gone?

Copy link
Author

@sameo sameo Jan 11, 2017

Choose a reason for hiding this comment

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

This string was returned by runC itself. Other runtimes may not decide to return the same string.
To be runtime agnostic, I think the only thing we can safely check here is that this execsync call really failed.

oci/oci.go Outdated
// ExecSync execs a command in a container and returns it's stdout, stderr and return code.
func (r *Runtime) ExecSync(c *Container, command []string, timeout int64) (resp *ExecSyncResponse, err error) {
args := []string{"exec", c.name}
parentPipe, childPipe, err := os.Pipe()
Copy link
Member

Choose a reason for hiding this comment

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

I'd create a function in the oci package to wrap all of this? What do you think?

Copy link
Author

Choose a reason for hiding this comment

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

By "all of this" do you mean the pipe and temporary file creation ?

Copy link
Member

Choose a reason for hiding this comment

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

By "all of this" do you mean the pipe and temporary file creation ?

yes

@laijs
Copy link
Contributor

laijs commented Jan 11, 2017

When executing a command inside a running container those runtimes will create that shim process and terminate.

I don't understand it, if the argument "-d" is not added to "runtime exec", the runtime exec process must wait the new process of the container.

@sameo
Copy link
Author

sameo commented Jan 11, 2017

@laijs You're correct. I'll try playing with that. It does not work currently with clear containers, but it may be a simpler path.

@laijs
Copy link
Contributor

laijs commented Jan 11, 2017

I like this approach also, but I think you need to add "-d" to "runtime exec" in ExecSync() common.c

@sameo
Copy link
Author

sameo commented Jan 11, 2017

@laijs I assume you meant adding -d to the conmon exec arguments ?

@sameo
Copy link
Author

sameo commented Jan 11, 2017

@laijs Done, conmon now calls exec with -d.

@mrunalp
Copy link
Member

mrunalp commented Jan 12, 2017

Thanks! I will test this out today.

/* Wait for the container process and record its exit code */
while ((pid = waitpid(-1, &status, 0)) > 0) {
printf("PID %d exited\n", pid);
int exit_status = WEXITSTATUS(status);
Copy link
Member

Choose a reason for hiding this comment

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

We were doing this conversion up in the go code so need to remove the conversion from https://github.com/kubernetes-incubator/cri-o/blob/master/oci/oci.go#L338

Copy link
Author

Choose a reason for hiding this comment

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

Done, thanks for spotting that one.

Samuel Ortiz added 5 commits January 14, 2017 02:00
waitpid fills its second argument with a value that
contains the process exit code in the 8 least significant
bits. Instead of returning the complete value and then
convert it from ocid, return the exit status directly
by using WEXITSTATUS from conmon.

Signed-off-by: Samuel Ortiz <[email protected]>
And not a hardcoded "pidfile".

Signed-off-by: Samuel Ortiz <[email protected]>
Some OCI container runtimes (in particular the hypervisor
based ones) will typically create a shim process between
the hypervisor and the runtime caller, in order to not
rely on the hypervisor process for e.g. forwarding the
output streams or getting a command exit code.

With these runtimes we need to monitor a different process
than the runtime one when executing a command inside a
running container. The natural place to do so is conmon
and thus we add a new option to conmon for calling the
runtime exec command, monitor the PID and then return the
running command exit code through the sync pipe to the
parent.

Signed-off-by: Samuel Ortiz <[email protected]>
Some OCI container runtimes (in particular the hypervisor
based ones) will typically create a shim process between
the hypervisor and the runtime caller, in order to not
rely on the hypervisor process for e.g. forwarding the
output streams or getting a command exit code.

When executing a command inside a running container those
runtimes will create that shim process and terminate.
Therefore calling and monitoring them directly from
ExecSync() will fail. Instead we need to have a subreaper
calling the runtime and monitoring the shim process.
This change uses conmon as the subreaper from ExecSync(),
monitors the shim process and read the exec'ed command
exit code from the synchronization pipe.

Signed-off-by: Samuel Ortiz <[email protected]>
"executable file not found in" is part of a runc
specific output when 'runc exec' fails.
This prevents the execsync failure to pass when running
ocid with other runtimes than runc.

Signed-off-by: Samuel Ortiz <[email protected]>
@mrunalp
Copy link
Member

mrunalp commented Jan 16, 2017

LGTM

@mrunalp mrunalp merged commit 2421aba into cri-o:master Jan 16, 2017
@cyphar
Copy link
Contributor

cyphar commented Jan 24, 2017

Sorry that I was on holiday while this patch was being reviewed. I don't like this because now all of conmon has bifoccated logic for exec and non-exec. The code is getting really hard to follow...

@cyphar
Copy link
Contributor

cyphar commented Jan 24, 2017

I'll do a bit of cleanup in #162 ...

@sameo
Copy link
Author

sameo commented Jan 24, 2017

@cyphar Sounds good. Please ping me when you have it ready so that I can verify it does not break Clear Containers.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants