From e3183739bbe85772c195877fff66b377bb2265b5 Mon Sep 17 00:00:00 2001 From: Ruslan Shestopalyuk Date: Fri, 15 Aug 2025 08:12:04 -0700 Subject: [PATCH] Options to run Fantom with address and thread sanitizers enabled (#53300) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/53300 # Changelog: [Internal] - This adds two new modes to Fantom, allowing to run the native (C++) side with enabling either: * Address sanitizer, which would detect memory overwrites * Thread sanitizer, which can detect potential threading issues, such as race conditions This are opt-in for now. Currently, both modes already detect different errors, which have a high chance to be real issues and have to be fixed. Reviewed By: lenaic Differential Revision: D80339524 fbshipit-source-id: 784ddb9f0af79a04b074e107e4955724d54d5685 --- .../react-native-fantom/__docs__/README.md | 18 +++++++++++++ .../runner/EnvironmentOptions.js | 12 +++++++++ private/react-native-fantom/runner/utils.js | 27 ++++++++++++++++++- 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/private/react-native-fantom/__docs__/README.md b/private/react-native-fantom/__docs__/README.md index 60e9c90b243..f14e152bc7c 100644 --- a/private/react-native-fantom/__docs__/README.md +++ b/private/react-native-fantom/__docs__/README.md @@ -220,6 +220,24 @@ FANTOM_DEBUG_CPP=1 yarn fantom This would start a debugging session in VS Code with an initial breakpoint in the Fantom CLI binary. +#### Address and thread sanitizer for C++ + +It's also possible to run the C++ side with the thread or address sanitizer +enabled, which can help with debugging memory and threading issues. + +To enable the address sanitizer, run your fantom test with the flag +`FANTOM_ENABLE_ASAN`: + +```shell +FANTOM_ENABLE_ASAN=1 yarn fantom +``` + +For thread sanitizer, correspondingly, use flag `FANTOM_ENABLE_TSAN`: + +```shell +FANTOM_ENABLE_TSAN=1 yarn fantom +``` + ### Profiling #### JS sampling profiler diff --git a/private/react-native-fantom/runner/EnvironmentOptions.js b/private/react-native-fantom/runner/EnvironmentOptions.js index bf9ac5e3704..553049aacaa 100644 --- a/private/react-native-fantom/runner/EnvironmentOptions.js +++ b/private/react-native-fantom/runner/EnvironmentOptions.js @@ -10,6 +10,8 @@ const VALID_ENVIRONMENT_VARIABLES = [ 'FANTOM_DEBUG_CPP', + 'FANTOM_ENABLE_ASAN', + 'FANTOM_ENABLE_TSAN', 'FANTOM_ENABLE_CPP_DEBUGGING', 'FANTOM_FORCE_CI_MODE', 'FANTOM_FORCE_OSS_BUILD', @@ -67,6 +69,16 @@ export const debugJS: boolean = Boolean(process.env.FANTOM_DEBUG_JS); export const profileJS: boolean = Boolean(process.env.FANTOM_PROFILE_JS); +/** + * Enables address sanitizer (ASAN) build mode for the C++ side. + */ +export const enableASAN: boolean = Boolean(process.env.FANTOM_ENABLE_ASAN); + +/** + * Enables thread sanitizer (TSAN) build mode for the C++ side. + */ +export const enableTSAN: boolean = Boolean(process.env.FANTOM_ENABLE_TSAN); + export const enableJSMemoryInstrumentation: boolean = Boolean( process.env.FANTOM_ENABLE_JS_MEMORY_INSTRUMENTATION, ); diff --git a/private/react-native-fantom/runner/utils.js b/private/react-native-fantom/runner/utils.js index eefc4d3cb99..1dcdc26774e 100644 --- a/private/react-native-fantom/runner/utils.js +++ b/private/react-native-fantom/runner/utils.js @@ -54,7 +54,32 @@ export function getHermesCompilerTarget(variant: HermesVariant): string { export function getBuckModesForPlatform( enableRelease: boolean = false, ): $ReadOnlyArray { - const mode = enableRelease ? 'opt' : 'dev'; + let mode = enableRelease ? 'opt' : 'dev'; + + if (enableRelease) { + if (EnvironmentOptions.enableASAN || EnvironmentOptions.enableTSAN) { + printConsoleLog({ + type: 'console-log', + level: 'warn', + message: + 'ASAN and TSAN are not supported in release mode. Use dev mode instead.', + }); + } + } else { + if (EnvironmentOptions.enableASAN) { + printConsoleLog({ + type: 'console-log', + level: 'warn', + message: + 'ASAN and TSAN modes cannot be used together. Using ASAN mode as a fallback.', + }); + mode = 'dev-asan'; + } else if (EnvironmentOptions.enableASAN) { + mode = 'dev-asan'; + } else if (EnvironmentOptions.enableTSAN) { + mode = 'dev-tsan'; + } + } let osPlatform; switch (os.platform()) {