From: Cedric Le Goater Date: Wed, 26 May 2010 19:43:53 +0000 (+0200) Subject: introduce a sync API X-Git-Tag: lxc-0.7.0~54 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3c22086fe242c1cbb51e1df4add3052d3618c2ca;p=thirdparty%2Flxc.git introduce a sync API 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 Signed-off-by: Daniel Lezcano --- diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am index 510bc9dca..7c9ae7ad9 100644 --- a/src/lxc/Makefile.am +++ b/src/lxc/Makefile.am @@ -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 \ diff --git a/src/lxc/start.c b/src/lxc/start.c index c79cf708d..2d4539634 100644 --- a/src/lxc/start.c +++ b/src/lxc/start.c @@ -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 index 000000000..c1dc0a9c5 --- /dev/null +++ b/src/lxc/sync.c @@ -0,0 +1,133 @@ +/* + * lxc: linux Container library + * + * (C) Copyright IBM Corp. 2007, 2008 + * + * Authors: + * Daniel Lezcano + * + * 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 +#include +#include +#include +#include + +#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 index 000000000..a733d2e58 --- /dev/null +++ b/src/lxc/sync.h @@ -0,0 +1,45 @@ +/* + * lxc: linux Container library + * + * (C) Copyright IBM Corp. 2007, 2008 + * + * Authors: + * Daniel Lezcano + * + * 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