mirror of
https://github.com/facebook/rocksdb.git
synced 2026-10-23 08:09:02 +03:00
Enable core dumps for sanitizer crash tests (#15131)
Summary: Pull Request resolved: https://github.com/facebook/rocksdb/pull/15131 ASAN and other sanitizer runtimes can disable coredumps or terminate without a core after the test driver sets its shell core limit. This leaves sanitizer stress-test failures with an LLDB stack but no core for the DB artifact. Configure ASAN_OPTIONS, TSAN_OPTIONS, and UBSAN_OPTIONS during sanitizer crash-test steps so reports terminate with a core-generating abort and core dumping remains enabled. Preserve caller-provided options and the existing Make fallback semantics. Keep the behavior scoped to test steps and crash targets. Enabling sanitizer cores raises a concern that the generated core-dump artifacts can be large because they include the process working set. Reduce RocksDB's cache and memtable contribution to the core size without replacing the normal randomized test configuration. Add a db_crashtest cache/write-buffer size multiplier that is applied after each iteration chooses its values, and pass 0.5 from ASAN, TSAN, and UBSAN crash lanes. For the simple profile, cache_size remains randomized with 8/32 MiB becoming 4/16 MiB, while the 32 MiB write buffer becomes 16 MiB. Preserve RocksDB's 64 KiB minimum write-buffer size and leave non-sanitizer lanes unchanged. Reviewed By: rban1 Differential Revision: D116666171 fbshipit-source-id: aa157cfa255bb637d4a68e54ea2039db779fdc53
This commit is contained in:
committed by
meta-codesync[bot]
parent
d3a82f28ce
commit
42fca1bb39
@@ -48,6 +48,7 @@ DEFAULT_LIVENESS_NO_PROGRESS_TIMEOUT_SEC = 300
|
||||
REMOTE_DB_LIVENESS_TIMEOUT_MULTIPLIER = 2
|
||||
_FAULT_INJECTION_LOG_DIR_NAME = "fault_injection_logs"
|
||||
_REMOTE_DB_URI_FLAGS = ("--env_uri", "--fs_uri")
|
||||
_MIN_WRITE_BUFFER_SIZE = 64 * 1024
|
||||
|
||||
|
||||
def get_random_seed(override):
|
||||
@@ -76,6 +77,25 @@ def stress_cmd_env():
|
||||
return env
|
||||
|
||||
|
||||
def apply_cache_and_write_buffer_size_multiplier(params):
|
||||
"""Scale selected per-iteration memory sizes while preserving randomization."""
|
||||
multiplier = params.pop("cache_and_write_buffer_size_multiplier", None)
|
||||
if multiplier is None:
|
||||
return
|
||||
if not math.isfinite(multiplier) or multiplier <= 0:
|
||||
raise ValueError(
|
||||
"cache_and_write_buffer_size_multiplier must be finite and greater than zero"
|
||||
)
|
||||
|
||||
for name, minimum in (
|
||||
("cache_size", 1),
|
||||
("write_buffer_size", _MIN_WRITE_BUFFER_SIZE),
|
||||
):
|
||||
value = params.get(name)
|
||||
if value is not None and value > 0:
|
||||
params[name] = max(int(value * multiplier), minimum)
|
||||
|
||||
|
||||
def normalize_remote_db_args(args):
|
||||
"""Normalize supported remote URI flags to --flag=value form."""
|
||||
normalized_args = []
|
||||
@@ -1053,6 +1073,7 @@ multiops_txn_params = {
|
||||
|
||||
def finalize_and_sanitize(src_params):
|
||||
dest_params = {k: v() if callable(v) else v for (k, v) in src_params.items()}
|
||||
apply_cache_and_write_buffer_size_multiplier(dest_params)
|
||||
if is_release_mode():
|
||||
dest_params["read_fault_one_in"] = 0
|
||||
if dest_params.get("compression_max_dict_bytes") == 0:
|
||||
@@ -2586,6 +2607,11 @@ def main():
|
||||
parser.add_argument("--test_tiered_storage", action="store_true")
|
||||
parser.add_argument("--cleanup_cmd") # ignore old option for now
|
||||
parser.add_argument("--print_stderr_separately", action="store_true", default=False)
|
||||
parser.add_argument(
|
||||
"--cache_and_write_buffer_size_multiplier",
|
||||
type=float,
|
||||
help="Scale each iteration's cache_size and write_buffer_size",
|
||||
)
|
||||
|
||||
all_params = dict(
|
||||
list(default_params.items())
|
||||
@@ -2613,6 +2639,11 @@ def main():
|
||||
# unknown_args are passed directly to db_stress
|
||||
|
||||
args, unknown_args = parser.parse_known_args(remain_args)
|
||||
multiplier = args.cache_and_write_buffer_size_multiplier
|
||||
if multiplier is not None and (not math.isfinite(multiplier) or multiplier <= 0):
|
||||
parser.error(
|
||||
"--cache_and_write_buffer_size_multiplier must be finite and greater than zero"
|
||||
)
|
||||
test_tmpdir = os.environ.get(_TEST_DIR_ENV_VAR)
|
||||
if test_tmpdir is not None and not is_remote_db:
|
||||
isdir = False
|
||||
|
||||
@@ -153,6 +153,49 @@ class DBCrashTestTest(unittest.TestCase):
|
||||
any(arg.startswith("--use_coro_db_api=") for arg in command)
|
||||
)
|
||||
|
||||
def test_cache_and_write_buffer_size_multiplier_preserves_randomization(self):
|
||||
db_crashtest = self.load_db_crashtest()
|
||||
cache_sizes = iter([8 * 1024 * 1024, 32 * 1024 * 1024])
|
||||
params = self.build_params(
|
||||
db_crashtest.default_params,
|
||||
{
|
||||
"cache_size": lambda: next(cache_sizes),
|
||||
"write_buffer_size": 32 * 1024 * 1024,
|
||||
"cache_and_write_buffer_size_multiplier": 0.5,
|
||||
},
|
||||
)
|
||||
|
||||
first_command, _ = db_crashtest.gen_cmd(params, [])
|
||||
second_command, _ = db_crashtest.gen_cmd(params, [])
|
||||
|
||||
self.assertIn("--cache_size=4194304", first_command)
|
||||
self.assertIn("--cache_size=16777216", second_command)
|
||||
self.assertIn("--write_buffer_size=16777216", first_command)
|
||||
self.assertIn("--write_buffer_size=16777216", second_command)
|
||||
self.assertFalse(
|
||||
any(
|
||||
arg.startswith("--cache_and_write_buffer_size_multiplier=")
|
||||
for arg in first_command
|
||||
)
|
||||
)
|
||||
|
||||
def test_cache_and_write_buffer_size_multiplier_respects_write_buffer_minimum(
|
||||
self,
|
||||
):
|
||||
db_crashtest = self.load_db_crashtest()
|
||||
params = self.build_params(
|
||||
db_crashtest.default_params,
|
||||
{
|
||||
"write_buffer_size": 64 * 1024,
|
||||
"cache_and_write_buffer_size_multiplier": 0.5,
|
||||
},
|
||||
)
|
||||
|
||||
finalized = db_crashtest.finalize_and_sanitize(params)
|
||||
|
||||
self.assertEqual(64 * 1024, finalized["write_buffer_size"])
|
||||
self.assertNotIn("cache_and_write_buffer_size_multiplier", finalized)
|
||||
|
||||
def test_get_ev_parent_dir_preserves_existing_contents(self):
|
||||
os.makedirs(self.expected_dir)
|
||||
marker = os.path.join(self.expected_dir, "marker")
|
||||
|
||||
Reference in New Issue
Block a user