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 \
#include "monitor.h"
#include "commands.h"
#include "console.h"
+#include "sync.h"
lxc_log_define(lxc_start, lxc);
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)) {
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)) {
*/
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;
}
}
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;
}
}
- /* 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;
goto out_abort;
}
- close(handler->sv[1]);
+ lxc_sync_fini(handler);
return 0;
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;
}
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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