mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 00:19:48 +00:00
[vm] Enable check_initialization_order for ASAN, ensure tools/test.py always passes ASAN options, make Random be initialized during VM startup
Running tools/test.py locally behaves differently than on the bots because the bots will have special environment variables set. => We want also local runs of tools/test.py to report ASAN errors, so this CL moves the setting of environment variables to tools/test.py Furthermore we enable "additional check_initialization_order=true" asan option to detect ordering issues when initializing global state. Make the IsolateGroup::isolate_group_random_ heap allocated on VM startup to avoid initialization ordering issue (turns out our `Random` can depend on embedder entropy source callback being available) Also add locking around assigning of isolate group ids -- without it we could have two threads racing and possibly getting the same id. See b/149978682 Change-Id: I41b9a34c66934dcc0d3804233f5acf09004ba3bd Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/136630 Commit-Queue: Martin Kustermann <kustermann@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com> Reviewed-by: Alexander Thomas <athom@google.com> Reviewed-by: Alexander Aprelev <aam@google.com>
This commit is contained in:
parent
6a90bf5d54
commit
767943850f
|
@ -7,6 +7,7 @@ import 'dart:io';
|
|||
|
||||
import 'package:smith/smith.dart';
|
||||
import 'package:test_runner/src/test_configurations.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
|
||||
import 'configuration.dart';
|
||||
import 'path.dart';
|
||||
|
@ -993,3 +994,23 @@ class OptionParseException implements Exception {
|
|||
void _fail(String message) {
|
||||
throw OptionParseException(message);
|
||||
}
|
||||
|
||||
// Returns a map of environment variables to be used with sanitizers.
|
||||
final Map<String, String> sanitizerEnvironmentVariables = (() {
|
||||
final environment = <String, String>{};
|
||||
final testMatrixFile = "tools/bots/test_matrix.json";
|
||||
final config = json.decode(File(testMatrixFile).readAsStringSync());
|
||||
config['sanitizer_options'].forEach((String key, dynamic value) {
|
||||
environment[key] = value as String;
|
||||
});
|
||||
var symbolizerPath =
|
||||
config['sanitizer_symbolizer'][Platform.operatingSystem] as String;
|
||||
if (symbolizerPath != null) {
|
||||
symbolizerPath = path.join(Directory.current.path, symbolizerPath);
|
||||
environment['ASAN_SYMBOLIZER_PATH'] = symbolizerPath;
|
||||
environment['MSAN_SYMBOLIZER_PATH'] = symbolizerPath;
|
||||
environment['TSAN_SYMBOLIZER_PATH'] = symbolizerPath;
|
||||
}
|
||||
|
||||
return environment;
|
||||
})();
|
||||
|
|
|
@ -12,6 +12,7 @@ import "package:status_file/expectation.dart";
|
|||
import 'command.dart';
|
||||
import 'command_output.dart';
|
||||
import 'configuration.dart';
|
||||
import 'options.dart';
|
||||
import 'output_log.dart';
|
||||
import 'process_queue.dart';
|
||||
import 'test_file.dart';
|
||||
|
@ -381,8 +382,8 @@ class RunningProcess {
|
|||
}
|
||||
|
||||
Map<String, String> _createProcessEnvironment() {
|
||||
var environment = Map<String, String>.from(io.Platform.environment);
|
||||
|
||||
final environment = Map<String, String>.from(io.Platform.environment);
|
||||
environment.addAll(sanitizerEnvironmentVariables);
|
||||
if (command.environmentOverrides != null) {
|
||||
for (var key in command.environmentOverrides.keys) {
|
||||
environment[key] = command.environmentOverrides[key];
|
||||
|
|
|
@ -208,8 +208,8 @@ char* Dart::Init(const uint8_t* vm_isolate_snapshot,
|
|||
Timeline::Init();
|
||||
TimelineBeginEndScope tbes(Timeline::GetVMStream(), "Dart::Init");
|
||||
#endif
|
||||
Isolate::InitVM();
|
||||
IsolateGroup::Init();
|
||||
Isolate::InitVM();
|
||||
PortMap::Init();
|
||||
FreeListElement::Init();
|
||||
ForwardingCorpse::Init();
|
||||
|
|
|
@ -235,6 +235,10 @@ IsolateGroup::IsolateGroup(std::shared_ptr<IsolateGroupSource> source,
|
|||
shared_class_table_(new SharedClassTable()),
|
||||
store_buffer_(new StoreBuffer()),
|
||||
heap_(nullptr) {
|
||||
{
|
||||
WriteRwLocker wl(ThreadState::Current(), isolate_groups_rwlock_);
|
||||
id_ = isolate_group_random_->NextUInt64();
|
||||
}
|
||||
}
|
||||
|
||||
IsolateGroup::~IsolateGroup() {
|
||||
|
@ -566,9 +570,12 @@ void IsolateGroup::Init() {
|
|||
isolate_groups_rwlock_ = new RwLock();
|
||||
ASSERT(isolate_groups_ == nullptr);
|
||||
isolate_groups_ = new IntrusiveDList<IsolateGroup>();
|
||||
isolate_group_random_ = new Random();
|
||||
}
|
||||
|
||||
void IsolateGroup::Cleanup() {
|
||||
delete isolate_group_random_;
|
||||
isolate_group_random_ = nullptr;
|
||||
delete isolate_groups_rwlock_;
|
||||
isolate_groups_rwlock_ = nullptr;
|
||||
ASSERT(isolate_groups_->IsEmpty());
|
||||
|
@ -2365,7 +2372,7 @@ Dart_IsolateShutdownCallback Isolate::shutdown_callback_ = nullptr;
|
|||
Dart_IsolateCleanupCallback Isolate::cleanup_callback_ = nullptr;
|
||||
Dart_IsolateGroupCleanupCallback Isolate::cleanup_group_callback_ = nullptr;
|
||||
|
||||
Random IsolateGroup::isolate_group_random_ = {};
|
||||
Random* IsolateGroup::isolate_group_random_ = nullptr;
|
||||
Monitor* Isolate::isolate_creation_monitor_ = nullptr;
|
||||
intptr_t Isolate::application_isolates_count_ = 0;
|
||||
intptr_t Isolate::total_isolates_count_ = 0;
|
||||
|
|
|
@ -532,9 +532,9 @@ class IsolateGroup : public IntrusiveDListEntry<IsolateGroup> {
|
|||
|
||||
static RwLock* isolate_groups_rwlock_;
|
||||
static IntrusiveDList<IsolateGroup>* isolate_groups_;
|
||||
static Random* isolate_group_random_;
|
||||
|
||||
static Random isolate_group_random_;
|
||||
uint64_t id_ = isolate_group_random_.NextUInt64();
|
||||
uint64_t id_ = 0;
|
||||
|
||||
std::unique_ptr<SharedClassTable> shared_class_table_;
|
||||
std::unique_ptr<StoreBuffer> store_buffer_;
|
||||
|
|
|
@ -1378,21 +1378,13 @@
|
|||
"arguments": [
|
||||
"--sanitizer=asan",
|
||||
"runtime"
|
||||
],
|
||||
"environment": {
|
||||
"ASAN_OPTIONS": "handle_segv=0:detect_leaks=1:detect_stack_use_after_return=0:disable_coredump=0:abort_on_error=1",
|
||||
"ASAN_SYMBOLIZER_PATH": "buildtools/linux-x64/clang/bin/llvm-symbolizer"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "vm tests",
|
||||
"arguments": [
|
||||
"-ndartk-asan-linux-release-${arch}"
|
||||
],
|
||||
"environment": {
|
||||
"ASAN_OPTIONS": "handle_segv=0:detect_leaks=1:detect_stack_use_after_return=0:disable_coredump=0:abort_on_error=1",
|
||||
"ASAN_SYMBOLIZER_PATH": "buildtools/linux-x64/clang/bin/llvm-symbolizer"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -1420,21 +1412,13 @@
|
|||
"arguments": [
|
||||
"--sanitizer=lsan",
|
||||
"runtime"
|
||||
],
|
||||
"environment": {
|
||||
"ASAN_OPTIONS": "handle_segv=0:detect_leaks=1:detect_stack_use_after_return=0:disable_coredump=0:abort_on_error=1",
|
||||
"ASAN_SYMBOLIZER_PATH": "buildtools/linux-x64/clang/bin/llvm-symbolizer"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "vm tests",
|
||||
"arguments": [
|
||||
"-ndartk-lsan-linux-release-${arch}"
|
||||
],
|
||||
"environment": {
|
||||
"ASAN_OPTIONS": "handle_segv=0:detect_leaks=1:detect_stack_use_after_return=0:disable_coredump=0:abort_on_error=1",
|
||||
"ASAN_SYMBOLIZER_PATH": "buildtools/linux-x64/clang/bin/llvm-symbolizer"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -1461,21 +1445,13 @@
|
|||
"arguments": [
|
||||
"--sanitizer=msan",
|
||||
"runtime"
|
||||
],
|
||||
"environment": {
|
||||
"MSAN_OPTIONS": "handle_segv=0:detect_leaks=1:detect_stack_use_after_return=0:disable_coredump=0:abort_on_error=1",
|
||||
"MSAN_SYMBOLIZER_PATH": "buildtools/linux-x64/clang/bin/llvm-symbolizer"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "vm tests",
|
||||
"arguments": [
|
||||
"-ndartk-msan-linux-release-${arch}"
|
||||
],
|
||||
"environment": {
|
||||
"MSAN_OPTIONS": "handle_segv=0:detect_leaks=1:detect_stack_use_after_return=0:disable_coredump=0:abort_on_error=1",
|
||||
"MSAN_SYMBOLIZER_PATH": "buildtools/linux-x64/clang/bin/llvm-symbolizer"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -1502,21 +1478,13 @@
|
|||
"arguments": [
|
||||
"--sanitizer=tsan",
|
||||
"runtime"
|
||||
],
|
||||
"environment": {
|
||||
"TSAN_OPTIONS": "handle_segv=0:disable_coredump=0:abort_on_error=1",
|
||||
"TSAN_SYMBOLIZER_PATH": "buildtools/linux-x64/clang/bin/llvm-symbolizer"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "vm tests",
|
||||
"arguments": [
|
||||
"-ndartk-tsan-linux-release-${arch}"
|
||||
],
|
||||
"environment": {
|
||||
"TSAN_OPTIONS": "handle_segv=0:disable_coredump=0:abort_on_error=1",
|
||||
"TSAN_SYMBOLIZER_PATH": "buildtools/linux-x64/clang/bin/llvm-symbolizer"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -1544,19 +1512,13 @@
|
|||
"arguments": [
|
||||
"--sanitizer=ubsan",
|
||||
"runtime"
|
||||
],
|
||||
"environment": {
|
||||
"UBSAN_OPTIONS": "handle_segv=0:disable_coredump=0:abort_on_error=1"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "vm tests",
|
||||
"arguments": [
|
||||
"-ndartk-ubsan-linux-release-${arch}"
|
||||
],
|
||||
"environment": {
|
||||
"UBSAN_OPTIONS": "handle_segv=0:disable_coredump=0:abort_on_error=1"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -3496,5 +3458,15 @@
|
|||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"sanitizer_options": {
|
||||
"ASAN_OPTIONS": "check_initialization_order=true:handle_segv=0:detect_leaks=1:detect_stack_use_after_return=0:disable_coredump=0:abort_on_error=1",
|
||||
"MSAN_OPTIONS": "check_initialization_order=true:handle_segv=0:detect_leaks=1:detect_stack_use_after_return=0:disable_coredump=0:abort_on_error=1",
|
||||
"TSAN_OPTIONS": "handle_segv=0:disable_coredump=0:abort_on_error=1",
|
||||
"UBSAN_OPTIONS": "handle_segv=0:disable_coredump=0:abort_on_error=1"
|
||||
},
|
||||
"sanitizer_symbolizer": {
|
||||
"linux": "buildtools/linux-x64/clang/bin/llvm-symbolizer",
|
||||
"macos": "buildtools/mac-x64/clang/bin/llvm-symbolizer"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
# for details. All rights reserved. Use of this source code is governed by a
|
||||
# BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import io
|
||||
import json
|
||||
import multiprocessing
|
||||
import optparse
|
||||
import os
|
||||
|
@ -312,10 +314,10 @@ def BuildOneConfig(options, targets, target_os, mode, arch, sanitizer):
|
|||
return (build_config, command, using_goma)
|
||||
|
||||
|
||||
def RunOneBuildCommand(build_config, args):
|
||||
def RunOneBuildCommand(build_config, args, env):
|
||||
start_time = time.time()
|
||||
print(' '.join(args))
|
||||
process = subprocess.Popen(args, stdin=None)
|
||||
process = subprocess.Popen(args, env=env, stdin=None)
|
||||
process.wait()
|
||||
if process.returncode != 0:
|
||||
NotifyBuildDone(build_config, success=False, start=start_time)
|
||||
|
@ -326,10 +328,11 @@ def RunOneBuildCommand(build_config, args):
|
|||
return 0
|
||||
|
||||
|
||||
def RunOneGomaBuildCommand(args):
|
||||
def RunOneGomaBuildCommand(options):
|
||||
(env, args) = options
|
||||
try:
|
||||
print(' '.join(args))
|
||||
process = subprocess.Popen(args, stdin=None)
|
||||
process = subprocess.Popen(args, env=env, stdin=None)
|
||||
process.wait()
|
||||
print(' '.join(args) + " done.")
|
||||
return process.returncode
|
||||
|
@ -337,6 +340,21 @@ def RunOneGomaBuildCommand(args):
|
|||
return 1
|
||||
|
||||
|
||||
def SanitizerEnvironmentVariables():
|
||||
with io.open('tools/bots/test_matrix.json', encoding='utf-8') as fd:
|
||||
config = json.loads(fd.read())
|
||||
env = dict()
|
||||
for k, v in config['sanitizer_options'].items():
|
||||
env[str(k)] = str(v)
|
||||
symbolizer_path = config['sanitizer_symbolizer'].get(HOST_OS, None)
|
||||
if symbolizer_path:
|
||||
symbolizer_path = str(os.path.join(DART_ROOT, symbolizer_path))
|
||||
env['ASAN_SYMBOLIZER_PATH'] = symbolizer_path
|
||||
env['MSAN_SYMBOLIZER_PATH'] = symbolizer_path
|
||||
env['TSAN_SYMBOLIZER_PATH'] = symbolizer_path
|
||||
return env
|
||||
|
||||
|
||||
def Main():
|
||||
starttime = time.time()
|
||||
# Parse the options.
|
||||
|
@ -354,6 +372,12 @@ def Main():
|
|||
if not GenerateBuildfilesIfNeeded():
|
||||
return 1
|
||||
|
||||
# If binaries are built with sanitizers we should use those flags.
|
||||
# If the binaries are not built with sanitizers the flag should have no
|
||||
# effect.
|
||||
env = dict(os.environ)
|
||||
env.update(SanitizerEnvironmentVariables())
|
||||
|
||||
# Build all targets for each requested configuration.
|
||||
configs = []
|
||||
for target_os in options.os:
|
||||
|
@ -370,8 +394,8 @@ def Main():
|
|||
if args is None:
|
||||
return 1
|
||||
if goma:
|
||||
goma_builds.append(args)
|
||||
elif RunOneBuildCommand(build_config, args) != 0:
|
||||
goma_builds.append([env, args])
|
||||
elif RunOneBuildCommand(build_config, args, env=env) != 0:
|
||||
return 1
|
||||
|
||||
# Run goma builds in parallel.
|
||||
|
|
Loading…
Reference in a new issue