[lxc-devel] [PATCH 2/2] let lxc-monitor command ask a lxc-monitord instance to quit

Dwight Engen dwight.engen at oracle.com
Fri Dec 6 20:36:50 UTC 2013


Once lxc-monitord receives a quit request from lxc-monitor, it will then
return from the mainloop every time an event occurs on any of its fds and
check if it has any clients left. When there are no more it exits. This
allows lxc-monitord to quit immediately instead of waiting the normal 30
seconds for more clients, potentially freeing up lxcpath for unmounting.

Signed-off-by: Dwight Engen <dwight.engen at oracle.com>
---
 doc/lxc-monitor.sgml.in | 22 ++++++++++++++++++++++
 src/lxc/lxc_monitor.c   | 33 +++++++++++++++++++++++++++++++--
 src/lxc/lxc_monitord.c  | 18 +++++++++++++++---
 3 files changed, 68 insertions(+), 5 deletions(-)

diff --git a/doc/lxc-monitor.sgml.in b/doc/lxc-monitor.sgml.in
index abd668a..e57314e 100644
--- a/doc/lxc-monitor.sgml.in
+++ b/doc/lxc-monitor.sgml.in
@@ -50,6 +50,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     <cmdsynopsis>
       <command>lxc-monitor</command>
       <arg choice="opt">-n <replaceable>name</replaceable></arg>
+      <arg choice="opt">-Q <replaceable>name</replaceable></arg>
     </cmdsynopsis>
   </refsynopsisdiv>
 
@@ -75,6 +76,27 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
   </refsect1>
 
+  <refsect1>
+    <title>Options</title>
+
+    <variablelist>
+      <varlistentry>
+	<term>
+	  <option>-Q, --quit</option>
+	</term>
+	<listitem>
+	  <para>
+	    Ask the lxc-monitord daemon on each given <command>lxcpath</command>
+	    to quit. After receiving this command, lxc-monitord will exit
+	    immediately as soon as it has no clients instead of waiting the
+	    normal 30 seconds for new clients. This is useful if you need to
+	    unmount the filesystem <command>lxcpath</command> is on.
+	  </para>
+	</listitem>
+      </varlistentry>
+     </variablelist>
+  </refsect1>
+
   &commonoptions;
 
   <refsect1>
diff --git a/src/lxc/lxc_monitor.c b/src/lxc/lxc_monitor.c
index 4f56308..63ab68b 100644
--- a/src/lxc/lxc_monitor.c
+++ b/src/lxc/lxc_monitor.c
@@ -35,7 +35,18 @@
 
 lxc_log_define(lxc_monitor_ui, lxc_monitor);
 
+static bool quit_monitord;
+
+static int my_parser(struct lxc_arguments* args, int c, char* arg)
+{
+	switch (c) {
+	case 'Q': quit_monitord = true; break;
+	}
+	return 0;
+}
+
 static const struct option my_longopts[] = {
+	{"quit", no_argument, 0, 'Q'},
 	LXC_COMMON_OPTIONS
 };
 
@@ -48,10 +59,11 @@ lxc-monitor monitors the state of the NAME container\n\
 \n\
 Options :\n\
   -n, --name=NAME   NAME for name of the container\n\
-                    NAME may be a regular expression",
+                    NAME may be a regular expression\n\
+  -Q, --quit        tell lxc-monitord to quit\n",
 	.name     = ".*",
 	.options  = my_longopts,
-	.parser   = NULL,
+	.parser   = my_parser,
 	.checker  = NULL,
 	.lxcpath_additional = -1,
 };
@@ -74,6 +86,23 @@ int main(int argc, char *argv[])
 			 my_args.progname, my_args.quiet, my_args.lxcpath[0]))
 		return -1;
 
+	if (quit_monitord) {
+		int ret = EXIT_SUCCESS;
+		for (i = 0; i < my_args.lxcpath_cnt; i++) {
+			int fd;
+
+			fd = lxc_monitor_open(my_args.lxcpath[i]);
+			if (fd < 0) {
+				ERROR("Unable to open monitor on path:%s", my_args.lxcpath[i]);
+				ret = EXIT_FAILURE;
+				continue;
+			}
+			write(fd, "quit", 4);
+			close(fd);
+		}
+		return ret;
+	}
+
 	len = strlen(my_args.name) + 3;
 	regexp = malloc(len + 3);
 	if (!regexp) {
diff --git a/src/lxc/lxc_monitord.c b/src/lxc/lxc_monitord.c
index 381b2d6..fc83f01 100644
--- a/src/lxc/lxc_monitord.c
+++ b/src/lxc/lxc_monitord.c
@@ -29,6 +29,7 @@
 #include <string.h>
 #include <stdlib.h>
 #include <fcntl.h>
+#include <sys/epoll.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/param.h>
@@ -70,6 +71,7 @@ struct lxc_monitor {
 };
 
 static struct lxc_monitor mon;
+static int quit;
 
 static int lxc_monitord_fifo_create(struct lxc_monitor *mon)
 {
@@ -135,8 +137,18 @@ static int lxc_monitord_sock_handler(int fd, uint32_t events, void *data,
 {
 	struct lxc_monitor *mon = data;
 
-	lxc_monitord_sockfd_remove(mon, fd);
-	return 0;
+	if (events & EPOLLIN) {
+		int rc;
+		char buf[4];
+
+		rc = read(fd, buf, sizeof(buf));
+		if (rc > 0 && !strncmp(buf, "quit", 4))
+			quit = 1;
+	}
+
+	if (events & EPOLLHUP)
+		lxc_monitord_sockfd_remove(mon, fd);
+	return quit;
 }
 
 static int lxc_monitord_sock_accept(int fd, uint32_t events, void *data,
@@ -393,7 +405,7 @@ int main(int argc, char *argv[])
 		ret = lxc_mainloop(&mon.descr, 1000 * 30);
 		if (mon.clientfds_cnt <= 0)
 		{
-			NOTICE("no clients for 30 seconds, exiting");
+			NOTICE("no remaining clients, exiting");
 			break;
 		}
 	}
-- 
1.8.3.1





More information about the lxc-devel mailing list