4

How can I detect whether thread sanitizer has been turned on for a build using gcc 5? Neither one of the two between __has_feature(thread_sanitizer) nor __SANITIZE_THREAD__ work

#include <iostream>

using std::cout;
using std::endl;

int main() {
    cout << __has_feature(thread_sanitizer) << endl;
    cout << __SANITIZE_THREAD__ << endl;
}

https://wandbox.org/permlink/t5qYme4Whyj54aYV. This compiles on the versions of clang that have thread sanitizer; but not for some gcc versions (5 in particular)


Both the feature check and the __SANITIZE_THREAD__ macro are useful in detecting when the thread sanitizer has been turned on so tests can suppress false-negatives (eg. when thread sanitizer catches a bug that's not actually a data race) See this for more

Curious
  • 20,870
  • 8
  • 61
  • 146
  • Regarding the close vote: how can I make the question clearer? – Curious Aug 14 '19 at 18:15
  • 2
    Just curious; *why* do you need this? – Jesper Juhl Aug 14 '19 at 18:17
  • @JesperJuhl TSAN does not instrument some things correctly in the older gcc-based versions. Eg. inline assembly – Curious Aug 14 '19 at 18:19
  • 1
    "Detect" how? When? Why? On what? – Lightness Races in Orbit Aug 14 '19 at 18:19
  • @LightnessRacesinOrbit I'm not sure what you mean, isn't there just one meaning for "detecting" in this context? Similar to https://en.cppreference.com/w/cpp/feature_test? – Curious Aug 14 '19 at 18:21
  • "TSAN does not instrument some things correctly in the older gcc-based versions" - Isn't the solution then to just use *newer* gcc versions (which may also bring other benefits)? – Jesper Juhl Aug 14 '19 at 18:22
  • What I'm saying is you did not tell us what sort of outcome you want. Do you need a macro? A variable? A function call? A command-line utility? What? – Lightness Races in Orbit Aug 14 '19 at 18:22
  • @JesperJuhl I would, but some libraries that we support rely can't yet migrate to the newer versions of the compiler since the targetted client code uses the older version – Curious Aug 14 '19 at 18:23
  • @LightnessRacesinOrbit Not quite sure what it means to be binary-safe in this context, but I can't really control when everyone using the library upgrades their compiler. Nor can I do it myself – Curious Aug 14 '19 at 18:26
  • 4
    `__SANITIZE_THREAD__` is only present in gcc-7+. – Marc Glisse Aug 14 '19 at 18:30
  • @LightnessRacesinOrbit I have to what exactly? – Curious Aug 14 '19 at 18:31
  • @LightnessRacesinOrbit I see; the build model for this library is not the typical "distribute binary and include headers" one that you might be talking about (correct me if I am wrong). It gets included and built from scratch along with the client code. – Curious Aug 14 '19 at 18:35
  • @LightnessRacesinOrbit I didn't even consider binary compatibility? You bought it up no? What am I missing? I just need the library code to compile and run without error on older compiler versions (which is why I need the feature check macro) – Curious Aug 14 '19 at 18:41
  • 1
    @Curious Okay, that makes sense – Lightness Races in Orbit Aug 14 '19 at 18:42

1 Answers1

4

I don't know, but as a last resort, the following command line will find a #define if it exists:

diff <(gcc -dM -E -x c /dev/null) <(gcc -fsanitize=thread -dM -E -x c /dev/null)

On my gcc 7.4.0 it outputs:

> #define __SANITIZE_THREAD__ 1

...which means that __SANITIZE_THREAD__ is defined to be 1 if you are using -fsanitize=thread, but is not defined if you don't. So you should guard your code behind an #ifdef __SANITIZE_THREAD__ rather than just using the symbol directly.

Additional Info:

I checked the gcc source and the __SANITIZE_THREAD__ macro was not introduced until version 7.1.0.

Wyck
  • 10,311
  • 6
  • 39
  • 60
  • 2
    It isn't a last resort, it comes not long after checking the doc. Sadly, in this case, with gcc-5, the output is empty. – Marc Glisse Aug 14 '19 at 18:33
  • Could you explain how this command works? And what it's doing? Curious :) – Curious Aug 14 '19 at 18:47
  • 1
    @Curious `-E` invokes the preprocessor and sends the output to stdout. `-dM` displays defined macros (requires `-E` to be specified). `-x c` forces compilation as a C file. (you could alternatively use `-x c++`) and finally `/dev/null` sets the input file to `/dev/null` (nothing). Then it diffs this preprocessor output with and without the `-fsanitize=thread` flag. – Wyck Aug 14 '19 at 18:57