Commit 3c22086f by Cedric Le Goater Committed by Daniel Lezcano

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: 's avatarCedric Le Goater <clg@fr.ibm.com> Signed-off-by: 's avatarDaniel Lezcano <dlezcano@fr.ibm.com>
parent ee70bf78
...@@ -31,6 +31,7 @@ liblxc_so_SOURCES = \ ...@@ -31,6 +31,7 @@ liblxc_so_SOURCES = \
cgroup.c cgroup.h \ cgroup.c cgroup.h \
lxc.h \ lxc.h \
utils.c utils.h \ utils.c utils.h \
sync.c sync.h \
namespace.h namespace.c \ namespace.h namespace.c \
conf.c conf.h \ conf.c conf.h \
confile.c confile.h \ confile.c confile.h \
......
...@@ -124,6 +124,7 @@ int signalfd(int fd, const sigset_t *mask, int flags) ...@@ -124,6 +124,7 @@ int signalfd(int fd, const sigset_t *mask, int flags)
#include "monitor.h" #include "monitor.h"
#include "commands.h" #include "commands.h"
#include "console.h" #include "console.h"
#include "sync.h"
lxc_log_define(lxc_start, lxc); lxc_log_define(lxc_start, lxc);
...@@ -414,29 +415,19 @@ void lxc_abort(const char *name, struct lxc_handler *handler) ...@@ -414,29 +415,19 @@ void lxc_abort(const char *name, struct lxc_handler *handler)
static int do_start(void *data) static int do_start(void *data)
{ {
struct lxc_handler *handler = data; struct lxc_handler *handler = data;
int err = -1, sync;
if (sigprocmask(SIG_SETMASK, &handler->oldmask, NULL)) { if (sigprocmask(SIG_SETMASK, &handler->oldmask, NULL)) {
SYSERROR("failed to set sigprocmask"); SYSERROR("failed to set sigprocmask");
return -1; return -1;
} }
close(handler->sv[1]); lxc_sync_fini_parent(handler);
/* Be sure we don't inherit this after the exec */ /* Tell the parent task it can begin to configure the
fcntl(handler->sv[0], F_SETFD, FD_CLOEXEC); * container and wait for it to finish
*/
/* Tell our father he can begin to configure the container */ if (lxc_sync_barrier_parent(handler, LXC_SYNC_CONFIGURE))
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");
return -1; return -1;
}
/* Setup the container, ip, names, utsname, ... */ /* Setup the container, ip, names, utsname, ... */
if (lxc_setup(handler->name, handler->conf)) { if (lxc_setup(handler->name, handler->conf)) {
...@@ -462,24 +453,18 @@ static int do_start(void *data) ...@@ -462,24 +453,18 @@ static int do_start(void *data)
return -1; return -1;
out_warn_father: out_warn_father:
/* If the exec fails, tell that to our father */ lxc_sync_wake_parent(handler, LXC_SYNC_POST_CONFIGURE);
if (write(handler->sv[0], &err, sizeof(err)) < 0)
SYSERROR("failed to write the socket");
return -1; return -1;
} }
int lxc_spawn(struct lxc_handler *handler) int lxc_spawn(struct lxc_handler *handler)
{ {
int clone_flags; int clone_flags;
int sync;
int failed_before_rename = 0; int failed_before_rename = 0;
const char *name = handler->name; const char *name = handler->name;
/* Synchro socketpair */ if (lxc_sync_init(handler))
if (socketpair(AF_LOCAL, SOCK_STREAM, 0, handler->sv)) {
SYSERROR("failed to create communication socketpair");
return -1; return -1;
}
clone_flags = CLONE_NEWUTS|CLONE_NEWPID|CLONE_NEWIPC|CLONE_NEWNS; clone_flags = CLONE_NEWUTS|CLONE_NEWPID|CLONE_NEWIPC|CLONE_NEWNS;
if (!lxc_list_empty(&handler->conf->network)) { if (!lxc_list_empty(&handler->conf->network)) {
...@@ -491,8 +476,7 @@ int lxc_spawn(struct lxc_handler *handler) ...@@ -491,8 +476,7 @@ int lxc_spawn(struct lxc_handler *handler)
*/ */
if (lxc_create_network(&handler->conf->network)) { if (lxc_create_network(&handler->conf->network)) {
ERROR("failed to create the network"); ERROR("failed to create the network");
close(handler->sv[0]); lxc_sync_fini(handler);
close(handler->sv[1]);
return -1; return -1;
} }
} }
...@@ -505,13 +489,10 @@ int lxc_spawn(struct lxc_handler *handler) ...@@ -505,13 +489,10 @@ int lxc_spawn(struct lxc_handler *handler)
goto out_delete_net; goto out_delete_net;
} }
close(handler->sv[0]); lxc_sync_fini_child(handler);
/* Wait for the child to be ready */ if (lxc_sync_wait_child(handler, LXC_SYNC_CONFIGURE))
if (read(handler->sv[1], &sync, sizeof(sync)) <= 0) {
ERROR("sync read failure : %m");
failed_before_rename = 1; failed_before_rename = 1;
}
if (lxc_rename_nsgroup(name, handler)) if (lxc_rename_nsgroup(name, handler))
goto out_delete_net; goto out_delete_net;
...@@ -527,17 +508,11 @@ int lxc_spawn(struct lxc_handler *handler) ...@@ -527,17 +508,11 @@ int lxc_spawn(struct lxc_handler *handler)
} }
} }
/* Tell the child to continue its initialization */ /* Tell the child to continue its initialization and wait for
if (write(handler->sv[1], &sync, sizeof(sync)) < 0) { * it to exec or return an error
SYSERROR("failed to write the socket"); */
goto out_abort; if (lxc_sync_barrier_child(handler, LXC_SYNC_POST_CONFIGURE))
} return -1;
/* 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;
}
if (handler->ops->post_start(handler, handler->data)) if (handler->ops->post_start(handler, handler->data))
goto out_abort; goto out_abort;
...@@ -548,7 +523,7 @@ int lxc_spawn(struct lxc_handler *handler) ...@@ -548,7 +523,7 @@ int lxc_spawn(struct lxc_handler *handler)
goto out_abort; goto out_abort;
} }
close(handler->sv[1]); lxc_sync_fini(handler);
return 0; return 0;
out_delete_net: out_delete_net:
...@@ -556,7 +531,7 @@ out_delete_net: ...@@ -556,7 +531,7 @@ out_delete_net:
lxc_delete_network(&handler->conf->network); lxc_delete_network(&handler->conf->network);
out_abort: out_abort:
lxc_abort(name, handler); lxc_abort(name, handler);
close(handler->sv[1]); lxc_sync_fini(handler);
return -1; return -1;
} }
......
/*
* 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);
}
/*
* 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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment