Currently, there is only a single pipe passed to lxc_controller
and it is used by lxc_controller to signal to the LXC driver that
the container is set up and ready to run. However, in the next
commit we will need to signal that the LXC driver has done its
part of startup process and thus the controller can proceed.
Unfortunately, virCommand handshake can't be used for this,
because it's already used to read controller's PID.
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
src/lxc/lxc_controller.c | 46 ++++++++++++++++++++++++++++------------
src/lxc/lxc_process.c | 21 +++++++++++-------
2 files changed, 46 insertions(+), 21 deletions(-)
diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
index 797547b05c..1c0a370d4b 100644
--- a/src/lxc/lxc_controller.c
+++ b/src/lxc/lxc_controller.c
@@ -100,7 +100,7 @@ struct _virLXCController {
virDomainObj *vm;
virDomainDef *def;
- int handshakeFd;
+ int handshakeFds[2]; /* { read FD, write FD } */
pid_t initpid;
@@ -194,7 +194,8 @@ static virLXCController *virLXCControllerNew(const char *name)
ctrl->timerShutdown = -1;
ctrl->firstClient = true;
ctrl->name = g_strdup(name);
- ctrl->handshakeFd = -1;
+ ctrl->handshakeFds[0] = -1;
+ ctrl->handshakeFds[1] = -1;
if (!(driver = virLXCControllerDriverNew()))
goto error;
@@ -311,7 +312,8 @@ static void virLXCControllerFree(virLXCController *ctrl)
virCgroupFree(ctrl->cgroup);
/* This must always be the last thing to be closed */
- VIR_FORCE_CLOSE(ctrl->handshakeFd);
+ for (i = 0; i < G_N_ELEMENTS(ctrl->handshakeFds); i++)
+ VIR_FORCE_CLOSE(ctrl->handshakeFds[i]);
g_free(ctrl);
}
@@ -348,7 +350,7 @@ static int
virLXCControllerConsoleSetNonblocking(virLXCControllerConsole *consol
static int virLXCControllerDaemonHandshake(virLXCController *ctrl)
{
- if (lxcContainerSendContinue(ctrl->handshakeFd) < 0) {
+ if (lxcContainerSendContinue(ctrl->handshakeFds[1]) < 0) {
virReportSystemError(errno, "%s",
_("error sending continue signal to daemon"));
return -1;
@@ -2402,8 +2404,9 @@ virLXCControllerRun(virLXCController *ctrl)
if (virLXCControllerDaemonHandshake(ctrl) < 0)
goto cleanup;
- /* and preemptively close handshakeFd */
- VIR_FORCE_CLOSE(ctrl->handshakeFd);
+ /* and preemptively close handshakeFds */
+ for (i = 0; i < G_N_ELEMENTS(ctrl->handshakeFds); i++)
+ VIR_FORCE_CLOSE(ctrl->handshakeFds[i]);
/* We must not hold open a dbus connection for life
* of LXC instance, since dbus-daemon is limited to
@@ -2431,6 +2434,26 @@ virLXCControllerRun(virLXCController *ctrl)
}
+static int
+parseFDPair(const char *arg,
+ int (*fd)[2])
+{
+ g_auto(GStrv) fds = NULL;
+
+ fds = g_strsplit(arg, ":", 0);
+
+ if (fds[0] == NULL || fds[1] == NULL || fds[2] != NULL ||
+ virStrToLong_i(fds[0], NULL, 10, &(*fd)[0]) < 0 ||
+ virStrToLong_i(fds[1], NULL, 10, &(*fd)[1]) < 0) {
+ fprintf(stderr, "malformed --handshakefd argument '%s'",
+ optarg);
+ return -1;
+ }
+
+ return 0;
+}
+
+
int main(int argc, char *argv[])
{
pid_t pid;
@@ -2439,7 +2462,7 @@ int main(int argc, char *argv[])
size_t nveths = 0;
char **veths = NULL;
int ns_fd[VIR_LXC_DOMAIN_NAMESPACE_LAST];
- int handshakeFd = -1;
+ int handshakeFds[2] = { -1, -1 };
bool bg = false;
const struct option options[] = {
{ "background", 0, NULL, 'b' },
@@ -2515,11 +2538,8 @@ int main(int argc, char *argv[])
break;
case 's':
- if (virStrToLong_i(optarg, NULL, 10, &handshakeFd) < 0) {
- fprintf(stderr, "malformed --handshakefd argument
'%s'",
- optarg);
+ if (parseFDPair(optarg, &handshakeFds) < 0)
goto cleanup;
- }
break;
case 'N':
@@ -2578,7 +2598,7 @@ int main(int argc, char *argv[])
goto cleanup;
}
- if (handshakeFd < 0) {
+ if (handshakeFds[0] < 0 || handshakeFds[1] < 0) {
fprintf(stderr, "%s: missing --handshakefd argument for container
PTY\n",
argv[0]);
goto cleanup;
@@ -2596,7 +2616,7 @@ int main(int argc, char *argv[])
if (!(ctrl = virLXCControllerNew(name)))
goto cleanup;
- ctrl->handshakeFd = handshakeFd;
+ memcpy(&ctrl->handshakeFds, &handshakeFds, sizeof(handshakeFds));
if (!(ctrl->securityManager = virSecurityManagerNew(securityDriver,
LXC_DRIVER_NAME, 0)))
diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c
index ac635efe7a..493e19f03d 100644
--- a/src/lxc/lxc_process.c
+++ b/src/lxc/lxc_process.c
@@ -939,7 +939,8 @@ virLXCProcessBuildControllerCmd(virLXCDriver *driver,
int *nsInheritFDs,
int *files,
size_t nfiles,
- int handshakefd,
+ int handshakefdW,
+ int handshakefdR,
int * const logfd,
const char *pidfile)
{
@@ -1003,12 +1004,13 @@ virLXCProcessBuildControllerCmd(virLXCDriver *driver,
virSecurityManagerGetModel(driver->securityManager));
virCommandAddArg(cmd, "--handshakefd");
- virCommandAddArgFormat(cmd, "%d", handshakefd);
+ virCommandAddArgFormat(cmd, "%d:%d", handshakefdR, handshakefdW);
for (i = 0; veths && veths[i]; i++)
virCommandAddArgList(cmd, "--veth", veths[i], NULL);
- virCommandPassFD(cmd, handshakefd, 0);
+ virCommandPassFD(cmd, handshakefdW, 0);
+ virCommandPassFD(cmd, handshakefdR, 0);
virCommandDaemonize(cmd);
virCommandSetPidFile(cmd, pidfile);
virCommandSetOutputFD(cmd, logfd);
@@ -1198,7 +1200,7 @@ int virLXCProcessStart(virConnectPtr conn,
g_autofree char *logfile = NULL;
int logfd = -1;
g_auto(GStrv) veths = NULL;
- int handshakefds[2] = { -1, -1 };
+ int handshakefds[4] = { -1, -1, -1, -1 }; /* two pipes */
off_t pos = -1;
char ebuf[1024];
g_autofree char *timestamp = NULL;
@@ -1369,7 +1371,8 @@ int virLXCProcessStart(virConnectPtr conn,
goto cleanup;
}
- if (virPipe(handshakefds) < 0)
+ if (virPipe(&handshakefds[0]) < 0 ||
+ virPipe(&handshakefds[2]) < 0)
goto cleanup;
if (!(cmd = virLXCProcessBuildControllerCmd(driver,
@@ -1379,6 +1382,7 @@ int virLXCProcessStart(virConnectPtr conn,
nsInheritFDs,
files, nfiles,
handshakefds[1],
+ handshakefds[2],
&logfd,
pidfile)))
goto cleanup;
@@ -1448,7 +1452,8 @@ int virLXCProcessStart(virConnectPtr conn,
virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, reason);
priv->doneStopEvent = false;
- if (VIR_CLOSE(handshakefds[1]) < 0) {
+ if (VIR_CLOSE(handshakefds[1]) < 0 ||
+ VIR_CLOSE(handshakefds[2]) < 0) {
virReportSystemError(errno, "%s", _("could not close handshake
fd"));
goto cleanup;
}
@@ -1553,8 +1558,8 @@ int virLXCProcessStart(virConnectPtr conn,
virCommandFree(cmd);
for (i = 0; i < nttyFDs; i++)
VIR_FORCE_CLOSE(ttyFDs[i]);
- VIR_FORCE_CLOSE(handshakefds[0]);
- VIR_FORCE_CLOSE(handshakefds[1]);
+ for (i = 0; i < G_N_ELEMENTS(handshakefds); i++)
+ VIR_FORCE_CLOSE(handshakefds[i]);
virObjectUnref(cfg);
virObjectUnref(caps);
--
2.26.3