On 08/09/2012 09:20 AM, Daniel P. Berrange wrote:
From: "Daniel P. Berrange" <berrange(a)redhat.com>
Add two new APIs virLockSpaceNewPostExecRestart and
virLockSpacePreExecRestart which allow a virLockSpacePtr
object to be created from a JSON object and saved to a
JSON object, for the purposes of re-exec'ing a process.
As well as saving the state in JSON format, the second
method will disable the O_CLOEXEC flag so that the open
file descriptors are preserved across the process re-exec()
Signed-off-by: Daniel P. Berrange <berrange(a)redhat.com>
---
Is virLockSpacePreExecRestart called in the parent prior to forking
(mostly good, with one caveat) or in the child between fork and exec
(bad, since you malloc and do a lot of other non-async-safe stuff)? If
the latter, we risk deadlock; if the former, then you have at least one
bug...
+
+virLockSpacePtr virLockSpaceNewPostExecRestart(virJSONValuePtr object)
+{
+ virLockSpacePtr lockspace;
+ virJSONValuePtr resources;
+ int n;
+ size_t i;
+
+ VIR_DEBUG("object=%p", object);
Would it be any better to pretty-print the contents of object instead of
just listing its address?
+ if (virJSONValueObjectGetNumberInt(child, "fd",
&res->fd) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Missing resource fd in JSON document"));
+ virLockSpaceResourceFree(res);
+ goto error;
+ }
+ if (virSetInherit(res->fd, false) < 0) {
+ virReportSystemError(errno, "%s",
+ _("Cannot enable close-on-exec flag"));
+ goto error;
Is the reparse loop called while the exec'd process is still
single-threaded, so as to avoid any races with the fds that are not yet
re-marked CLOEXEC?
+
+virJSONValuePtr virLockSpacePreExecRestart(virLockSpacePtr lockspace)
+{
+
+ if (virSetInherit(res->fd, true) < 0) {
+ virReportSystemError(errno, "%s",
+ _("Cannot disable close-on-exec flag"));
+ goto error;
+ }
...clearing O_CLOEXEC in the parent is wrong. You cannot clear
O_CLOEXEC until you are in the child (so as not to leak into any other
child process spawned by another thread), which really means that you
have to use virCommandPreserveFD instead of virSetInherit (virCommand
will then call virSetInherit in the child, between fork and exec, on
your behalf). But that makes it sound like you need to pass a
virCommandPtr in to this function, in addition to the lockspace.
Overall, looks like a mostly sane serialization - simpler than coding it
up in XML, and still robust to pass between parent and child, but you do
need to solve the CLOEXEC safety issues.
--
Eric Blake eblake(a)redhat.com +1-919-301-3266
Libvirt virtualization library
http://libvirt.org