Gitweb: http://git.fedorahosted.org/git/?p=cluster.git;a=commitdiff;h=4118eaa46e9d2c... Commit: 4118eaa46e9d2c61c59178dfe17df33d683669f9 Parent: db3b4f9b78de7f90e2e19c590b14e5f3ec57333e Author: Christine Caulfield ccaulfie@redhat.com AuthorDate: Tue Oct 23 15:22:31 2012 +0100 Committer: Christine Caulfield ccaulfie@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@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;
cluster-commits@lists.stg.fedorahosted.org