cluster: STABLE32 - fenced: fix potential tight loop reading /dev/zero

Christine Caulfield chrissie at fedoraproject.org
Tue Oct 23 14:48:08 UTC 2012


Gitweb:        http://git.fedorahosted.org/git/?p=cluster.git;a=commitdiff;h=4118eaa46e9d2c61c59178dfe17df33d683669f9
Commit:        4118eaa46e9d2c61c59178dfe17df33d683669f9
Parent:        db3b4f9b78de7f90e2e19c590b14e5f3ec57333e
Author:        Christine Caulfield <ccaulfie at redhat.com>
AuthorDate:    Tue Oct 23 15:22:31 2012 +0100
Committer:     Christine Caulfield <ccaulfie at redhat.com>
CommitterDate: Tue Oct 23 15:22:31 2012 +0100

fenced: fix potential tight loop reading /dev/zero

The FD returned from cman is not meant to be stored anywhere - this is documented in the header
file (which is the official source of documentation for the API). Under some circumstances cman
can return the FD for /dev/zero (which is always active) and if the client application stores i
this instead of the one it expects then it will loop forever.

It's probably VERY hard to reproduce this, there would need to be some data coming from cman
quite soon after startup for it to happen, though it has been seen.

See rhbz#856214

Signed-off-by: Christine Caulfield <ccaulfie at redhat.com>
---
 fence/fenced/fd.h          |    1 +
 fence/fenced/main.c        |    5 ++++-
 fence/fenced/member_cman.c |    5 +++++
 3 files changed, 10 insertions(+), 1 deletions(-)

diff --git a/fence/fenced/fd.h b/fence/fenced/fd.h
index 0be3332..8423d9d 100644
--- a/fence/fenced/fd.h
+++ b/fence/fenced/fd.h
@@ -270,6 +270,7 @@ int name_to_nodeid(char *name);
 struct node *get_new_node(struct fd *fd, int nodeid);
 void kick_node_from_cluster(int nodeid);
 void set_cman_dirty(void);
+int get_member_fd(void);
 
 /* recover.c */
 
diff --git a/fence/fenced/main.c b/fence/fenced/main.c
index 2339a5d..c7f6269 100644
--- a/fence/fenced/main.c
+++ b/fence/fenced/main.c
@@ -739,6 +739,7 @@ void cluster_dead(int ci)
 static void loop(void)
 {
 	int rv, i;
+	int cluster_fd_pos;
 	void (*workfn) (int ci);
 	void (*deadfn) (int ci);
 
@@ -751,7 +752,7 @@ static void loop(void)
 		goto out;
 	client_add(rv, process_listener, NULL);
 
-	rv = setup_cluster();
+	rv = cluster_fd_pos = setup_cluster();
 	if (rv < 0)
 		goto out;
 	client_add(rv, process_cluster, cluster_dead);
@@ -804,6 +805,8 @@ static void loop(void)
 	}
 
 	for (;;) {
+		/* We need to re-get the cluster FD each time */
+		pollfd[cluster_fd_pos].fd = get_member_fd();
 		rv = poll(pollfd, client_maxi + 1, -1);
 		if (rv == -1 && errno == EINTR) {
 			if (daemon_quit && list_empty(&domains))
diff --git a/fence/fenced/member_cman.c b/fence/fenced/member_cman.c
index ee879be..061136e 100644
--- a/fence/fenced/member_cman.c
+++ b/fence/fenced/member_cman.c
@@ -375,6 +375,11 @@ void close_cluster(void)
 	cman_finish(ch_admin);
 }
 
+int get_member_fd()
+{
+	return cman_get_fd(ch);
+}
+
 struct node *get_new_node(struct fd *fd, int nodeid)
 {
 	cman_node_t cn;


More information about the cluster-commits mailing list