]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
introduce a sync API
authorCedric Le Goater <clg@linux.vnet.ibm.com>
Wed, 26 May 2010 19:43:53 +0000 (21:43 +0200)
committerDaniel Lezcano <dlezcano@fr.ibm.com>
Wed, 26 May 2010 19:43:53 +0000 (21:43 +0200)
The following patch wrap the calls on the synchronisation
socketpair in a lxc_sync_ API. It hopefully clarifies what
is done in the start sequence to the expense of more lines
of code ...

Signed-off-by: Cedric Le Goater <clg@fr.ibm.com>
Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
src/lxc/Makefile.am
src/lxc/start.c
src/lxc/sync.c [new file with mode: 0644]
src/lxc/sync.h [new file with mode: 0644]

index 510bc9dcada6fc0097c3e66ca2d8d99d66a7c3d4..7c9ae7ad938996c1cfafa9dd75a05fc87aa9670f 100644 (file)
@@ -31,6 +31,7 @@ liblxc_so_SOURCES = \
        cgroup.c cgroup.h \
        lxc.h \
        utils.c utils.h \
+       sync.c sync.h \
        namespace.h namespace.c \
        conf.c conf.h \
        confile.c confile.h \
index c79cf708dda948af224a7ec40ca2f6c5574632b9..2d45396342b4df5fcd052463a012dd7ad4008287 100644 (file)
@@ -124,6 +124,7 @@ int signalfd(int fd, const sigset_t *mask, int flags)
 #include "monitor.h"
 #include "commands.h"
 #include "console.h"
+#include "sync.h"
 
 lxc_log_define(lxc_start, lxc);
 
@@ -414,29 +415,19 @@ void lxc_abort(const char *name, struct lxc_handler *handler)
 static int do_start(void *data)
 {
        struct lxc_handler *handler = data;
-       int err = -1, sync;
 
        if (sigprocmask(SIG_SETMASK, &handler->oldmask, NULL)) {
                SYSERROR("failed to set sigprocmask");
                return -1;
        }
 
-       close(handler->sv[1]);
+       lxc_sync_fini_parent(handler);
 
-       /* Be sure we don't inherit this after the exec */
-       fcntl(handler->sv[0], F_SETFD, FD_CLOEXEC);
-
-       /* Tell our father he can begin to configure the container */
-       if (write(handler->sv[0], &sync, sizeof(sync)) < 0) {
-               SYSERROR("failed to write socket");
-               return -1;
-       }
-
-       /* Wait for the father to finish the configuration */
-       if (read(handler->sv[0], &sync, sizeof(sync)) < 0) {
-               SYSERROR("failed to read socket");
+       /* Tell the parent task it can begin to configure the
+        * container and wait for it to finish
+        */
+       if (lxc_sync_barrier_parent(handler, LXC_SYNC_CONFIGURE))
                return -1;
-       }
 
        /* Setup the container, ip, names, utsname, ... */
        if (lxc_setup(handler->name, handler->conf)) {
@@ -462,24 +453,18 @@ static int do_start(void *data)
                return -1;
 
 out_warn_father:
-       /* If the exec fails, tell that to our father */
-       if (write(handler->sv[0], &err, sizeof(err)) < 0)
-               SYSERROR("failed to write the socket");
+       lxc_sync_wake_parent(handler, LXC_SYNC_POST_CONFIGURE);
        return -1;
 }
 
 int lxc_spawn(struct lxc_handler *handler)
 {
        int clone_flags;
-       int sync;
        int failed_before_rename = 0;
        const char *name = handler->name;
 
-       /* Synchro socketpair */
-       if (socketpair(AF_LOCAL, SOCK_STREAM, 0, handler->sv)) {
-               SYSERROR("failed to create communication socketpair");
+       if (lxc_sync_init(handler))
                return -1;
-       }
 
        clone_flags = CLONE_NEWUTS|CLONE_NEWPID|CLONE_NEWIPC|CLONE_NEWNS;
        if (!lxc_list_empty(&handler->conf->network)) {
@@ -491,8 +476,7 @@ int lxc_spawn(struct lxc_handler *handler)
                 */
                if (lxc_create_network(&handler->conf->network)) {
                        ERROR("failed to create the network");
-                       close(handler->sv[0]);
-                       close(handler->sv[1]);
+                       lxc_sync_fini(handler);
                        return -1;
                }
        }
@@ -505,13 +489,10 @@ int lxc_spawn(struct lxc_handler *handler)
                goto out_delete_net;
        }
 
-       close(handler->sv[0]);
-       
-       /* Wait for the child to be ready */
-       if (read(handler->sv[1], &sync, sizeof(sync)) <= 0) {
-               ERROR("sync read failure : %m");
+       lxc_sync_fini_child(handler);
+
+       if (lxc_sync_wait_child(handler, LXC_SYNC_CONFIGURE))
                failed_before_rename = 1;
-       }
 
        if (lxc_rename_nsgroup(name, handler))
                goto out_delete_net;
@@ -527,17 +508,11 @@ int lxc_spawn(struct lxc_handler *handler)
                }
        }
 
-       /* Tell the child to continue its initialization */
-       if (write(handler->sv[1], &sync, sizeof(sync)) < 0) {
-               SYSERROR("failed to write the socket");
-               goto out_abort;
-       }
-
-       /* Wait for the child to exec or returning an error */
-       if (read(handler->sv[1], &sync, sizeof(sync)) < 0) {
-               ERROR("failed to read the socket");
-               goto out_abort;
-       }
+       /* Tell the child to continue its initialization and wait for
+        * it to exec or return an error
+        */
+       if (lxc_sync_barrier_child(handler, LXC_SYNC_POST_CONFIGURE))
+               return -1;
 
        if (handler->ops->post_start(handler, handler->data))
                goto out_abort;
@@ -548,7 +523,7 @@ int lxc_spawn(struct lxc_handler *handler)
                goto out_abort;
        }
 
-       close(handler->sv[1]);
+       lxc_sync_fini(handler);
        return 0;
 
 out_delete_net:
@@ -556,7 +531,7 @@ out_delete_net:
                lxc_delete_network(&handler->conf->network);
 out_abort:
        lxc_abort(name, handler);
-       close(handler->sv[1]);
+       lxc_sync_fini(handler);
        return -1;
 }
 
diff --git a/src/lxc/sync.c b/src/lxc/sync.c
new file mode 100644 (file)
index 0000000..c1dc0a9
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * lxc: linux Container library
+ *
+ * (C) Copyright IBM Corp. 2007, 2008
+ *
+ * Authors:
+ * Daniel Lezcano <dlezcano at fr.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include "log.h"
+#include "start.h"
+
+lxc_log_define(lxc_sync, lxc);
+
+static int __sync_wait(int fd, int sequence)
+{
+       int sync = -1;
+       int ret;
+
+       ret = read(fd, &sync, sizeof(sync));
+       if (ret < 0) {
+               ERROR("sync wait failure : %m");
+               return -1;
+       }
+
+       if (!ret)
+               return 0;
+
+       if (sync != sequence) {
+               ERROR("invalid sequence number %d. expected %d",
+                     sync, sequence);
+               return -1;
+       }
+       return 0;
+}
+
+static int __sync_wake(int fd, int sequence)
+{
+       int sync = sequence;
+
+       if (write(fd, &sync, sizeof(sync)) < 0) {
+               ERROR("sync wake failure : %m");
+               return -1;
+       }
+       return 0;
+}
+
+static int __sync_barrier(int fd, int sequence)
+{
+       if (__sync_wake(fd, sequence))
+               return -1;
+       return __sync_wait(fd, sequence+1);
+}
+
+int lxc_sync_barrier_parent(struct lxc_handler *handler, int sequence)
+{
+       return __sync_barrier(handler->sv[0], sequence);
+}
+
+int lxc_sync_barrier_child(struct lxc_handler *handler, int sequence)
+{
+       return __sync_barrier(handler->sv[1], sequence);
+}
+
+int lxc_sync_wake_parent(struct lxc_handler *handler, int sequence)
+{
+       return __sync_wake(handler->sv[0], sequence);
+}
+
+int lxc_sync_wait_child(struct lxc_handler *handler, int sequence)
+{
+       return __sync_wait(handler->sv[1], sequence);
+}
+
+int lxc_sync_wake_child(struct lxc_handler *handler, int sequence)
+{
+       return __sync_wake(handler->sv[1], sequence);
+}
+
+int lxc_sync_init(struct lxc_handler *handler)
+{
+       if (socketpair(AF_LOCAL, SOCK_STREAM, 0, handler->sv)) {
+               SYSERROR("failed to create synchronization socketpair");
+               return -1;
+       }
+
+       /* Be sure we don't inherit this after the exec */
+       fcntl(handler->sv[0], F_SETFD, FD_CLOEXEC);
+
+       return 0;
+}
+
+void lxc_sync_fini_child(struct lxc_handler *handler)
+{
+       if (handler->sv[0] != -1) {
+               close(handler->sv[0]);
+               handler->sv[0] = -1;
+       }
+}
+
+void lxc_sync_fini_parent(struct lxc_handler *handler)
+{
+       if (handler->sv[1] != -1) {
+               close(handler->sv[1]);
+               handler->sv[1] = -1;
+       }
+}
+
+void lxc_sync_fini(struct lxc_handler *handler)
+{
+       lxc_sync_fini_child(handler);
+       lxc_sync_fini_parent(handler);
+}
diff --git a/src/lxc/sync.h b/src/lxc/sync.h
new file mode 100644 (file)
index 0000000..a733d2e
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * lxc: linux Container library
+ *
+ * (C) Copyright IBM Corp. 2007, 2008
+ *
+ * Authors:
+ * Daniel Lezcano <dlezcano at fr.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __lxc_sync_h
+#define __lxc_sync_h
+
+struct lxc_handler;
+
+enum {
+       LXC_SYNC_CONFIGURE,
+       LXC_SYNC_POST_CONFIGURE,
+       LXC_SYNC_RESTART,
+       LXC_SYNC_POST_RESTART,
+};
+
+int lxc_sync_init(struct lxc_handler *handler);
+void lxc_sync_fini(struct lxc_handler *);
+void lxc_sync_fini_parent(struct lxc_handler *);
+void lxc_sync_fini_child(struct lxc_handler *);
+int lxc_sync_wake_child(struct lxc_handler *, int);
+int lxc_sync_wait_child(struct lxc_handler *, int);
+int lxc_sync_wake_parent(struct lxc_handler *, int);
+int lxc_sync_barrier_parent(struct lxc_handler *, int);
+int lxc_sync_barrier_child(struct lxc_handler *, int);
+
+#endif