git » libfiu » commit 72c474d

libfiu: Increment recursion count at remote control functions

author Alberto Bertogli
2009-06-16 18:34:49 UTC
committer Alberto Bertogli
2009-06-16 19:17:07 UTC
parent f50ef946b445346457108e40b1d31c44283935ee

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 +18 -2
libfiu/fiu.c +5 -1
libfiu/internal.h +11 -0

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
+