From 72c474d8d7f37a0cdf2c2bed07b36b042323f54d Mon Sep 17 00:00:00 2001
From: Alberto Bertogli <albertito@blitiri.com.ar>
Date: Tue, 16 Jun 2009 15:34:49 -0300
Subject: [PATCH 35/48] libfiu: Increment recursion count at remote control functions

If the remote control functions are affected by the enabled failures, then
it can be useless after enabling some failure points when the POSIX
preload library is in use.

This patch makes the remote control functions increment the recursion
count to prevent this.

Signed-off-by: Alberto Bertogli <albertito@blitiri.com.ar>
---
 libfiu/fiu-rc.c   |   20 ++++++++++++++++++--
 libfiu/fiu.c      |    6 +++++-
 libfiu/internal.h |   11 +++++++++++
 3 files changed, 34 insertions(+), 3 deletions(-)
 create mode 100644 libfiu/internal.h

diff --git a/libfiu/fiu-rc.c b/libfiu/fiu-rc.c
index 678a4b8..83dcb83 100644
--- a/libfiu/fiu-rc.c
+++ b/libfiu/fiu-rc.c
@@ -18,6 +18,7 @@
 #define FIU_ENABLE 1
 
 #include "fiu-control.h"
+#include "internal.h"
 
 
 /* Max length of a line containing a control directive */
@@ -181,6 +182,11 @@ static void *rc_fifo_thread(void *unused)
 {
 	int fdr, fdw, r;
 
+	/* increment the recursion count so we're not affected by libfiu,
+	 * otherwise we could make the remote control useless by enabling all
+	 * failure points */
+	rec_count++;
+
 reopen:
 	fdr = open(npipe_path_in, O_RDONLY);
 	if (fdr < 0)
@@ -196,7 +202,9 @@ reopen:
 		r = rc_do_command(fdr, fdw);
 		if (r < 0 && errno != EPIPE) {
 			perror("libfiu: Error reading from remote control");
-			break;
+			close(fdr);
+			close(fdw);
+			goto reopen;
 		} else if (r == 0 || (r < 0 && errno == EPIPE)) {
 			/* one of the ends of the pipe was closed */
 			close(fdr);
@@ -221,25 +229,33 @@ static int _fiu_rc_fifo(const char *basename)
 {
 	pthread_t thread;
 
+	/* see rc_fifo_thread() */
+	rec_count++;
+
 	snprintf(npipe_path_in, PATH_MAX,"%s-%d.in", basename, getpid());
 	snprintf(npipe_path_out, PATH_MAX,"%s-%d.out", basename, getpid());
 
-	if (mknod(npipe_path_in, S_IFIFO | 0600, 0) != 0)
+	if (mknod(npipe_path_in, S_IFIFO | 0600, 0) != 0) {
+		rec_count--;
 		return -1;
+	}
 
 	if (mknod(npipe_path_out, S_IFIFO | 0600, 0) != 0) {
 		unlink(npipe_path_in);
+		rec_count--;
 		return -1;
 	}
 
 	if (pthread_create(&thread, NULL, rc_fifo_thread, NULL) != 0) {
 		unlink(npipe_path_in);
 		unlink(npipe_path_out);
+		rec_count--;
 		return -1;
 	}
 
 	atexit(fifo_atexit);
 
+	rec_count--;
 	return 0;
 }
 
diff --git a/libfiu/fiu.c b/libfiu/fiu.c
index 797fe00..f0c344b 100644
--- a/libfiu/fiu.c
+++ b/libfiu/fiu.c
@@ -11,6 +11,7 @@
 
 #include "fiu.h"
 #include "fiu-control.h"
+#include "internal.h"
 
 
 /* Different methods to decide when a point of failure fails */
@@ -66,10 +67,13 @@ static pthread_rwlock_t enabled_fails_lock = PTHREAD_RWLOCK_INITIALIZER;
  * for writing, and can call malloc() (for example), which can in turn call
  * fiu_fail() which can take the lock for reading.
  *
+ * It is also modified at fiu-rc.c, to prevent failing within the remote
+ * control thread.
+ *
  * Sadly, we have to use the GNU extension for TLS, so we do not resort to
  * pthread_[get|set]specific() which could be wrapped. Luckily it's available
  * almost everywhere. */
-static __thread int rec_count = 0;
+__thread int rec_count = 0;
 
 
 /* Maximum number of free elements in enabled_fails (used to decide when to
diff --git a/libfiu/internal.h b/libfiu/internal.h
new file mode 100644
index 0000000..2c3bfba
--- /dev/null
+++ b/libfiu/internal.h
@@ -0,0 +1,11 @@
+
+/* Some libfiu's internal declarations */
+
+#ifndef _INTERNAL_H
+#define _INTERNAL_H
+
+/* Recursion count, used both in fiu.c and fiu-rc.c */
+extern __thread int rec_count;
+
+#endif
+
-- 
1.6.2.2.646.gb214

