-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Fix ExecSync support for runtimes other than runC #310
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
Conversation
391b70f to
9fd2477
Compare
| run ocic ctr execsync --id "$ctr_id" doesnotexist | ||
| echo "$output" | ||
| [ "$status" -ne 0 ] | ||
| [[ "$output" =~ "executable file not found in" ]] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where has this gone?
There was a problem hiding this comment.
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() |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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 ?
There was a problem hiding this comment.
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
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. |
|
@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. |
|
I like this approach also, but I think you need to add "-d" to "runtime exec" in |
|
@laijs I assume you meant adding |
|
@laijs Done, conmon now calls exec with -d. |
|
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); |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
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]>
|
LGTM |
|
Sorry that I was on holiday while this patch was being reviewed. I don't like this because now all of |
|
I'll do a bit of cleanup in #162 ... |
|
@cyphar Sounds good. Please ping me when you have it ready so that I can verify it does not break Clear Containers. |
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:
-eoption toconmonto also monitor potential shim processes created by<runtime> execExecSyncto callconmoninstead of calling the runtime directly.ExecSyncalso now reads the exit status code back through the synchronization pipe.Fixes #309