git » libfiu » commit b2a80c7

WIP preload/posix: Stop failing functions after exit()

author Alberto Bertogli
2014-06-16 01:09:26 UTC
committer Alberto Bertogli
2014-06-16 01:09:26 UTC
parent ed26a7c1209e3dd94b7fb85ff447c082cce7227c

WIP preload/posix: Stop failing functions after exit()

preload/posix/codegen.c +33 -2
preload/posix/codegen.h +7 -0

diff --git a/preload/posix/codegen.c b/preload/posix/codegen.c
index 691d6f0..0b9123c 100644
--- a/preload/posix/codegen.c
+++ b/preload/posix/codegen.c
@@ -40,8 +40,7 @@ void *libc_symbol(const char *symbol)
 #endif
 }
 
-
-/* this runs after all function-specific constructors */
+/* This runs after all function-specific constructors */
 static void constructor_attr(250) _fiu_init_final(void)
 {
 	struct timeval tv;
@@ -57,3 +56,35 @@ static void constructor_attr(250) _fiu_init_final(void)
 	rec_dec();
 }
 
+/* Stop failing things when atexit() begins.
+ *
+ * The first time we fail some function, we register the function below, so we
+ * stop failing points at exiting time.
+ *
+ * TODO: explain why we want this.
+ * TODO: explain why we do it this way (on the first failure).
+ *  -> anything before main() is useless for gcov
+ *  -> this is not 100% bullet proof, but chances are if you are failing
+ *  points before main(), then you know what you're doing and will be less
+ *  surprised if writing to coverage fails.
+ *
+ * This is not thread-safe, but it's harmless, as the worst that can happen is
+ * that we run atexit() more than once.
+ */
+void _fiu_atexit(void)
+{
+	rec_inc();
+}
+
+static int _fiu_atexit_called = 0;
+
+void _fiu_register_atexit(void)
+{
+	/* TODO: optionally (how? environment?) do not do this. */
+	if (_fiu_atexit_called == 0) {
+		_fiu_atexit_called++;
+		printd("registering atexit\n");
+		atexit(_fiu_atexit);
+	}
+}
+
diff --git a/preload/posix/codegen.h b/preload/posix/codegen.h
index 2885da1..9215526 100644
--- a/preload/posix/codegen.h
+++ b/preload/posix/codegen.h
@@ -11,6 +11,9 @@ extern int __thread _fiu_called;
 /* Get a symbol from libc */
 void *libc_symbol(const char *symbol);
 
+/* Register our atexit() function. */
+void _fiu_register_atexit(void);
+
 /* Some compilers support constructor priorities. Since we don't rely on them,
  * but use them for clarity purposes, use a macro so libfiu builds on systems
  * where they're not supported.
@@ -122,6 +125,7 @@ void *libc_symbol(const char *symbol);
 								\
 		fstatus = fiu_fail(FIU_NAME);			\
 		if (fstatus != 0) {				\
+			_fiu_register_atexit();			\
 			r = (RTYPE) fiu_failinfo();		\
 			goto exit;				\
 		}
@@ -132,6 +136,7 @@ void *libc_symbol(const char *symbol);
 								\
 		fstatus = fiu_fail(FIU_NAME);			\
 		if (fstatus != 0) {				\
+			_fiu_register_atexit();			\
 			r = FAIL_RET;				\
 			goto exit;				\
 		}
@@ -143,6 +148,7 @@ void *libc_symbol(const char *symbol);
 								\
 		fstatus = fiu_fail(FIU_NAME);			\
 		if (fstatus != 0) {				\
+			_fiu_register_atexit();			\
 			void *finfo = fiu_failinfo();		\
 			if (finfo == NULL) {			\
 				errno = valid_errnos[random() % \
@@ -161,6 +167,7 @@ void *libc_symbol(const char *symbol);
 								\
 		fstatus = fiu_fail(FIU_NAME);			\
 		if (fstatus != 0) {				\
+			_fiu_register_atexit();			\
 			CNT -= random() % CNT;			\
 		}