xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Martin Lucina <martin@lucina.net>
To: xen-devel@lists.xenproject.org
Cc: Wei Liu <wei.liu2@citrix.com>, Martin Lucina <martin@lucina.net>,
	Ian Jackson <ian.jackson@eu.citrix.com>,
	Ian Campbell <ian.campbell@citrix.com>,
	Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Subject: [PATCH v3] xenconsole: Ensure exclusive access to console using locks
Date: Fri, 24 Jul 2015 17:29:41 +0200	[thread overview]
Message-ID: <1437751781-30700-1-git-send-email-martin@lucina.net> (raw)
In-Reply-To: <21938.21666.285588.16673@mariner.uk.xensource.com>

If more than one instance of xenconsole is run against the same DOMID
then each instance will only get some data. This change ensures
exclusive access to the console by obtaining an exclusive lock on
<XEN_LOCK_DIR>/xenconsole.<DOMID>.

The locking strategy used is based on
tools/libxl/libxl_internal.c:libxl__lock_domain_userdata().

Signed-off-by: Martin Lucina <martin@lucina.net>
Cc: Ian Jackson <ian.jackson@eu.citrix.com>
Cc: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Cc: Ian Campbell <ian.campbell@citrix.com>
Cc: Wei Liu <wei.liu2@citrix.com>
---
 .gitignore                  |  1 +
 tools/console/Makefile      |  6 ++++-
 tools/console/client/main.c | 55 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 61 insertions(+), 1 deletion(-)

diff --git a/.gitignore b/.gitignore
index f6ddb00..bccbd12 100644
--- a/.gitignore
+++ b/.gitignore
@@ -100,6 +100,7 @@ tools/blktap2/vhd/vhd-update
 tools/blktap2/vhd/vhd-util
 tools/console/xenconsole
 tools/console/xenconsoled
+tools/console/client/_paths.h
 tools/debugger/gdb/gdb-6.2.1-linux-i386-xen/*
 tools/debugger/gdb/gdb-6.2.1/*
 tools/debugger/gdb/gdb-6.2.1.tar.bz2
diff --git a/tools/console/Makefile b/tools/console/Makefile
index 71f8088..77e8f29 100644
--- a/tools/console/Makefile
+++ b/tools/console/Makefile
@@ -21,6 +21,7 @@ all: $(BIN)
 clean:
 	$(RM) *.a *.so *.o *.rpm $(BIN) $(DEPS)
 	$(RM) client/*.o daemon/*.o
+	$(RM) client/_paths.h
 
 .PHONY: distclean
 distclean: clean
@@ -28,9 +29,12 @@ distclean: clean
 xenconsoled: $(patsubst %.c,%.o,$(wildcard daemon/*.c))
 	$(CC) $(LDFLAGS) $^ -o $@ $(LDLIBS) $(LDLIBS_xenconsoled) $(APPEND_LDFLAGS)
 
-xenconsole: $(patsubst %.c,%.o,$(wildcard client/*.c))
+xenconsole: client/_paths.h $(patsubst %.c,%.o,$(wildcard client/*.c))
 	$(CC) $(LDFLAGS) $^ -o $@ $(LDLIBS) $(LDLIBS_xenconsole) $(APPEND_LDFLAGS)
 
+genpath-target = $(call buildmakevars2header,client/_paths.h)
+$(eval $(genpath-target))
+
 .PHONY: install
 install: $(BIN)
 	$(INSTALL_DIR) $(DESTDIR)/$(sbindir)
diff --git a/tools/console/client/main.c b/tools/console/client/main.c
index 753b3aa..ff9ac7d 100644
--- a/tools/console/client/main.c
+++ b/tools/console/client/main.c
@@ -18,7 +18,9 @@
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 \*/
 
+#include <sys/file.h>
 #include <sys/types.h>
+#include <sys/stat.h>
 #include <sys/socket.h>
 #include <sys/un.h>
 #include <stdio.h>
@@ -40,10 +42,13 @@
 
 #include <xenstore.h>
 #include "xenctrl.h"
+#include "_paths.h"
 
 #define ESCAPE_CHARACTER 0x1d
 
 static volatile sig_atomic_t received_signal = 0;
+static char lockfile[sizeof (XEN_LOCK_DIR "/xenconsole.") + 8] = { 0 };
+static int lockfd = -1;
 
 static void sighandler(int signum)
 {
@@ -267,6 +272,53 @@ static void restore_term_stdin(void)
 	restore_term(STDIN_FILENO, &stdin_old_attr);
 }
 
+/* The following locking strategy is based on that from
+ * libxl__domain_userdata_lock(), with the difference that we want to fail if we
+ * cannot acquire the lock rather than wait indefinitely.
+ */
+static void console_lock(int domid)
+{
+	struct stat stab, fstab;
+	int fd;
+
+	snprintf(lockfile, sizeof lockfile, "%s%d", XEN_LOCK_DIR "/xenconsole.", domid);
+
+	while (true) {
+		fd = open(lockfile, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
+		if (fd < 0)
+			err(errno, "Could not open %s", lockfile);
+
+		while (flock(fd, LOCK_EX | LOCK_NB)) {
+			if (errno == EINTR)
+				continue;
+			else
+				err(errno, "Could not lock %s", lockfile);
+		}
+		if (fstat(fd, &fstab))
+			err(errno, "Could not fstat %s", lockfile);
+		if (stat(lockfile, &stab)) {
+			if (errno != ENOENT)
+				err(errno, "Could not stat %s", lockfile);
+		} else {
+			if (stab.st_dev == fstab.st_dev && stab.st_ino == fstab.st_ino)
+				break;
+		}
+
+		close(fd);
+	}
+
+	lockfd = fd;
+	return;
+}
+
+static void console_unlock(void)
+{
+	if (lockfile[0] && lockfd != -1) {
+		unlink(lockfile);
+		close(lockfd);
+	}
+}
+
 int main(int argc, char **argv)
 {
 	struct termios attr;
@@ -382,6 +434,9 @@ int main(int argc, char **argv)
 		exit(EINVAL);
 	}
 
+	console_lock(domid);
+	atexit(console_unlock);
+
 	/* Set a watch on this domain's console pty */
 	if (!xs_watch(xs, path, ""))
 		err(errno, "Can't set watch for console pty");
-- 
2.1.4

  reply	other threads:[~2015-07-24 15:29 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-07-22 17:08 [PATCH] xenconsole: Allow non-interactive use Martin Lucina
2015-07-23  8:48 ` Ian Campbell
2015-07-23 10:53   ` Wei Liu
2015-07-23 15:09   ` Martin Lucina
2015-07-23 15:23     ` Ian Campbell
2015-07-24 11:30       ` [PATCH v2] " Martin Lucina
2015-07-24 13:13         ` Ian Campbell
2015-07-24 11:36       ` [PATCH] " Martin Lucina
2015-07-24 11:44         ` Ian Campbell
2015-07-24 12:51           ` [PATCH] xenconsole: Ensure exclusive access to console using locks Martin Lucina
2015-07-24 13:11             ` Ian Campbell
2015-07-24 13:35               ` Ian Jackson
2015-07-24 13:40               ` Martin Lucina
2015-07-24 13:54                 ` Ian Campbell
2015-07-24 13:32             ` Ian Jackson
2015-07-24 13:42               ` Martin Lucina
2015-07-24 14:47                 ` [PATCH v2] " Martin Lucina
2015-07-24 15:07                   ` Ian Jackson
2015-07-24 15:29                     ` Martin Lucina [this message]
2015-07-24 16:01                       ` [PATCH v3] " Ian Jackson
2015-07-27 12:44                         ` Martin Lucina
2015-07-27 13:29                           ` Wei Liu
2015-07-27 15:14                             ` Ian Campbell
2015-07-24 15:12                   ` [PATCH v2] " Ian Campbell
2015-07-24 13:42               ` [PATCH] " Ian Campbell

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1437751781-30700-1-git-send-email-martin@lucina.net \
    --to=martin@lucina.net \
    --cc=ian.campbell@citrix.com \
    --cc=ian.jackson@eu.citrix.com \
    --cc=stefano.stabellini@eu.citrix.com \
    --cc=wei.liu2@citrix.com \
    --cc=xen-devel@lists.xenproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).