[test] Enable TSAN thread leak detection for most tests.

Disable for tests that use dart:io's exit.

Add missing thread joins to cc tests.

TEST=tsan
Bug: https://github.com/dart-lang/sdk/issues/41811
Change-Id: Id4e1a468a986c886fb5ae9e9677b4d8d0281cc79
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/468880
Reviewed-by: Alexander Aprelev <aam@google.com>
Commit-Queue: Ryan Macnak <rmacnak@google.com>
This commit is contained in:
Ryan Macnak
2026-01-05 10:04:25 -08:00
committed by Commit Queue
parent c2dc8f62a3
commit cee7000c1a
7 changed files with 48 additions and 20 deletions
+36 -19
View File
@@ -10621,9 +10621,12 @@ TEST_CASE(DartAPI_InvokeVMServiceMethod) {
static Monitor* loop_test_lock = new Monitor();
static bool loop_test_exit = false;
static bool loop_reset_count = false;
static ThreadJoinId loop_test_join_id = OSThread::kInvalidThreadJoinId;
#if !defined(PRODUCT)
static void InvokeServiceMessages(uword param) {
loop_test_join_id = OSThread::GetCurrentThreadJoinId(OSThread::Current());
char buffer[1024];
Utils::SNPrint(buffer, sizeof(buffer),
R"({
@@ -10659,13 +10662,16 @@ static void InvokeServiceMessages(uword param) {
}
TEST_CASE(DartAPI_InvokeVMServiceMethod_Loop) {
MonitorLocker ml(loop_test_lock);
loop_test_exit = false;
loop_reset_count = false;
OSThread::Start("InvokeServiceMessages", InvokeServiceMessages, 0);
while (!loop_test_exit) {
ml.Wait();
{
MonitorLocker ml(loop_test_lock);
loop_test_exit = false;
loop_reset_count = false;
OSThread::Start("InvokeServiceMessages", InvokeServiceMessages, 0);
while (!loop_test_exit) {
ml.Wait();
}
}
OSThread::Join(loop_test_join_id);
}
#endif // !defined(PRODUCT)
@@ -10674,6 +10680,7 @@ static void HandleResponse(Dart_Port dest_port_id, Dart_CObject* message) {
}
static void CreateNativePorts(uword param) {
loop_test_join_id = OSThread::GetCurrentThreadJoinId(OSThread::Current());
uint32_t count = 0;
do {
const Dart_Port port_id = Dart_NewNativePort("tst", &HandleResponse, false);
@@ -10690,13 +10697,16 @@ static void CreateNativePorts(uword param) {
}
TEST_CASE(DartAPI_NativePort_Loop) {
MonitorLocker ml(loop_test_lock);
loop_test_exit = false;
loop_reset_count = false;
OSThread::Start("NativePort", CreateNativePorts, 0);
while (!loop_test_exit) {
ml.Wait();
{
MonitorLocker ml(loop_test_lock);
loop_test_exit = false;
loop_reset_count = false;
OSThread::Start("NativePort", CreateNativePorts, 0);
while (!loop_test_exit) {
ml.Wait();
}
}
OSThread::Join(loop_test_join_id);
}
#if !defined(PRODUCT)
@@ -10787,14 +10797,16 @@ TEST_CASE(DartAPI_TimelineEvents_Serialization) {
}
static void CreateTimelineEvents(uword param) {
{
MonitorLocker ml(loop_test_lock);
loop_test_exit = true;
ml.Notify();
}
loop_test_join_id = OSThread::GetCurrentThreadJoinId(OSThread::Current());
MonitorLocker ml(loop_test_lock);
loop_test_exit = true;
ml.Notify();
do {
MonitorLeaveScope leave(&ml);
ReportTimelineEvents();
} while (true);
} while (loop_test_exit);
}
UNIT_TEST_CASE(DartAPI_TimelineEvents_Loop) {
@@ -10821,7 +10833,6 @@ UNIT_TEST_CASE(DartAPI_TimelineEvents_Loop) {
printf("VM waiting for notification\n");
ml.Wait();
}
loop_test_exit = false;
}
result = Dart_Cleanup();
EXPECT(result == nullptr);
@@ -10832,6 +10843,12 @@ UNIT_TEST_CASE(DartAPI_TimelineEvents_Loop) {
result = Dart_Cleanup();
EXPECT(result == nullptr);
}
{
MonitorLocker ml(loop_test_lock);
loop_test_exit = false;
}
OSThread::Join(loop_test_join_id);
}
UNIT_TEST_CASE(DartAPI_TimelineEvents_NullFlowIdsHandledGracefully) {
+6
View File
@@ -299,10 +299,12 @@ void main() {
struct ChildThreadData {
Dart_Isolate isolate;
ThreadBarrier* barrier;
ThreadJoinId join_id;
};
static void SplayChild(uword parameter) {
ChildThreadData* data = reinterpret_cast<ChildThreadData*>(parameter);
data->join_id = OSThread::GetCurrentThreadJoinId(OSThread::Current());
ThreadBarrier* barrier = data->barrier;
Dart_EnterIsolate(data->isolate);
@@ -354,6 +356,10 @@ static void SplayTest(Dart_NativeEntryResolver resolver) {
barrier->Sync();
barrier->Release();
for (intptr_t i = 0; i < 2; i++) {
OSThread::Join(child_data[i].join_id);
}
}
struct Node {
@@ -7,6 +7,7 @@
// VMOptions=
// VMOptions=--use-slow-path
// SharedObjects=ffi_test_functions
// Environment=TSAN_OPTIONS=report_thread_leaks=0
import 'dart:io';
import 'dart:ffi';
import 'dart:isolate';
@@ -6,6 +6,8 @@
// invoke them with various basic values (nulls, ints, etc). This may result in
// Dart exceptions or hangs, but should never result in crashes.
// Environment=TSAN_OPTIONS=report_thread_leaks=0
// Library name is used by test.
library test.invoke_natives;
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
// OtherResources=process_child_script.dart
// Environment=TSAN_OPTIONS=report_thread_leaks=0
import "package:expect/expect.dart";
import 'package:path/path.dart';
+1
View File
@@ -4,6 +4,7 @@
// OtherResources=signal_test_script.dart
// OtherResources=signals_test_script.dart
// Environment=TSAN_OPTIONS=report_thread_leaks=0
import "dart:io";
import "dart:convert";
+1 -1
View File
@@ -3571,7 +3571,7 @@
"ASAN_OPTIONS": "abort_on_error=1:halt_on_error=1:symbolize=1:disable_coredump=0:handle_segv=0",
"LSAN_OPTIONS": "abort_on_error=1:halt_on_error=1:symbolize=1:disable_coredump=0:handle_segv=0",
"MSAN_OPTIONS": "abort_on_error=1:halt_on_error=1:symbolize=1:disable_coredump=0:handle_segv=0",
"TSAN_OPTIONS": "abort_on_error=1:halt_on_error=1:symbolize=1:disable_coredump=0:handle_segv=0:report_thread_leaks=0",
"TSAN_OPTIONS": "abort_on_error=1:halt_on_error=1:symbolize=1:disable_coredump=0:handle_segv=0",
"UBSAN_OPTIONS": "abort_on_error=1:halt_on_error=1:symbolize=1:disable_coredump=0:handle_segv=0:print_stacktrace=1"
},
"sanitizer_symbolizer": {