author | Alberto Bertogli
<albertito@blitiri.com.ar> 2014-06-16 01:09:26 UTC |
committer | Alberto Bertogli
<albertito@blitiri.com.ar> 2014-06-16 01:09:26 UTC |
parent | ed26a7c1209e3dd94b7fb85ff447c082cce7227c |
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; \ }