From: Daniel Lezcano Date: Wed, 7 Oct 2009 14:06:08 +0000 (+0200) Subject: handle the stop command X-Git-Tag: lxc_0_6_4~85 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2137dc998b884a4f3e0b1f365bb14f6ccd010243;p=thirdparty%2Flxc.git handle the stop command Handle the stop command. The stop command waits for the peer to disconnect, that means the peer has exited, so it is safe to return to the user control. By this way, we ensure a stop command followed by a start or a destroy won't fail with a race condition because the start command is not yet finised. Signed-off-by: Daniel Lezcano Signed-off-by: Michel Normand --- diff --git a/src/lxc/commands.c b/src/lxc/commands.c index 662ad9e15..4b7f81041 100644 --- a/src/lxc/commands.c +++ b/src/lxc/commands.c @@ -95,6 +95,8 @@ out_close: extern void lxc_console_remove_fd(int fd, struct lxc_tty_info *tty_info); extern int lxc_console_callback(int fd, struct lxc_request *request, struct lxc_handler *handler); +extern int lxc_stop_callback(int fd, struct lxc_request *request, + struct lxc_handler *handler); static int trigger_command(int fd, struct lxc_request *request, struct lxc_handler *handler) @@ -104,6 +106,7 @@ static int trigger_command(int fd, struct lxc_request *request, callback cb[LXC_COMMAND_MAX] = { [LXC_COMMAND_TTY] = lxc_console_callback, + [LXC_COMMAND_STOP] = lxc_stop_callback, }; if (request->type < 0 || request->type >= LXC_COMMAND_MAX) diff --git a/src/lxc/commands.h b/src/lxc/commands.h index b6c76c1f4..0e72e326f 100644 --- a/src/lxc/commands.h +++ b/src/lxc/commands.h @@ -25,6 +25,7 @@ enum { LXC_COMMAND_TTY, + LXC_COMMAND_STOP, LXC_COMMAND_MAX, }; diff --git a/src/lxc/stop.c b/src/lxc/stop.c index 72e2f87ef..896ab3b20 100644 --- a/src/lxc/stop.c +++ b/src/lxc/stop.c @@ -33,12 +33,13 @@ #include #include +#include "commands.h" lxc_log_define(lxc_stop, lxc); #define MAXPIDLEN 20 -int lxc_stop(const char *name) +int __lxc_stop(const char *name) { char init[MAXPATHLEN]; char val[MAXPIDLEN]; @@ -73,3 +74,61 @@ out_close: close(fd); return ret; } + +int lxc_stop(const char *name) +{ + struct lxc_command command = { + .request = { .type = LXC_COMMAND_STOP }, + }; + + int ret; + + ret = lxc_command(name, &command); + if (ret < 0) { + ERROR("failed to send command"); + return -1; + } + + /* we do not expect any answer, because we wait for the connection to be + * closed + */ + if (ret > 0) { + ERROR("stop request rejected for '%s': %s", + name, strerror(-command.answer.ret)); + return -1; + } + + INFO("'%s' has stopped", name); + + return 0; +} + +/*---------------------------------------------------------------------------- + * functions used by lxc-start mainloop + * to handle above command request. + *--------------------------------------------------------------------------*/ +extern int lxc_stop_callback(int fd, struct lxc_request *request, + struct lxc_handler *handler) +{ + struct lxc_answer answer; + int ret; + + answer.ret = kill(handler->pid, SIGKILL); + if (!answer.ret) + return 0; + + ret = send(fd, &answer, sizeof(answer), 0); + if (ret < 0) { + WARN("failed to send answer to the peer"); + goto out; + } + + if (ret != sizeof(answer)) { + ERROR("partial answer sent"); + goto out; + } + +out: + return -1; +} +