Skip to content

Commit 23cac7c

Browse files
mkustermannCommit Queue
authored andcommitted
[gardening] Make more robust test for mutator bit stealing mechanism
We also disable the test in hotreload mode, because threads that are stuck in ffi calls don't participate in hot-reload requests. This is something we may want to look into. Right now it's conservative in the sense that if an embedder did a `Dart_LookupClass()` in such a ffi call and then a reload happened, such a handle would possibly hold pointer to an old class object and weird things may happen. This fixes test failures in hot reload / rollback mode of `vm/dart/isolates/many_isolates_blocked_at_ffi_test` and also make it more robust. TEST=tests/ffi/dl_api_exit_enter_isolate_test Change-Id: I823d07a6ab04e62e051e4d22ec80cbc3649762a3 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/409100 Commit-Queue: Martin Kustermann <[email protected]> Reviewed-by: Ryan Macnak <[email protected]>
1 parent 041d86d commit 23cac7c

File tree

5 files changed

+52
-54
lines changed

5 files changed

+52
-54
lines changed

runtime/bin/ffi_test/ffi_test_functions_vmspecific.cc

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -890,15 +890,18 @@ DART_EXPORT void ThreadPoolTest_BarrierSync(
890890
Dart_Isolate (*dart_current_isolate)(),
891891
void (*dart_enter_isolate)(Dart_Isolate),
892892
void (*dart_exit_isolate)(),
893-
intptr_t num_threads) {
893+
intptr_t num_threads,
894+
bool exit_and_reenter_isolate) {
894895
// Guaranteed to be initialized exactly once (no race between multiple
895896
// threads).
896897
static std::mutex mutex;
897898
static std::condition_variable cvar;
898899
static intptr_t thread_count = 0;
899900

900901
const Dart_Isolate isolate = dart_current_isolate();
901-
dart_exit_isolate();
902+
if (exit_and_reenter_isolate) {
903+
dart_exit_isolate();
904+
}
902905
{
903906
std::unique_lock<std::mutex> lock(mutex);
904907
++thread_count;
@@ -907,7 +910,9 @@ DART_EXPORT void ThreadPoolTest_BarrierSync(
907910
}
908911
cvar.notify_all();
909912
}
910-
dart_enter_isolate(isolate);
913+
if (exit_and_reenter_isolate) {
914+
dart_enter_isolate(isolate);
915+
}
911916
}
912917

913918
////////////////////////////////////////////////////////////////////////////////
@@ -1284,9 +1289,11 @@ DART_EXPORT void SetFfiNativeResolverForTest(Dart_Handle url) {
12841289
ENSURE(!Dart_IsError(result));
12851290
}
12861291

1287-
DART_EXPORT void WaitUntilNThreadsEnterBarrier(intptr_t num_threads) {
1292+
DART_EXPORT void WaitUntilNThreadsEnterBarrier(intptr_t num_threads,
1293+
bool exit_and_reenter_isolate) {
12881294
ThreadPoolTest_BarrierSync(Dart_CurrentIsolate_DL, Dart_EnterIsolate_DL,
1289-
Dart_ExitIsolate_DL, num_threads);
1295+
Dart_ExitIsolate_DL, num_threads,
1296+
exit_and_reenter_isolate);
12901297
}
12911298

12921299
////////////////////////////////////////////////////////////////////////////////

runtime/tests/vm/dart/isolates/many_isolates_blocked_at_ffi_test.dart

Lines changed: 0 additions & 33 deletions
This file was deleted.

runtime/tests/vm/dart/isolates/thread_pool_test.dart

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,21 @@ typedef Dart_ExitIsolateNFT = Void Function();
2828
final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions");
2929

3030
final threadPoolBarrierSync = ffiTestFunctions.lookupFunction<
31-
Void Function(
32-
Pointer<NativeFunction<Dart_CurrentIsolateNFT>>,
33-
Pointer<NativeFunction<Dart_EnterIsolateNFT>>,
34-
Pointer<NativeFunction<Dart_ExitIsolateNFT>>,
35-
IntPtr),
36-
void Function(
37-
Pointer<NativeFunction<Dart_CurrentIsolateNFT>>,
38-
Pointer<NativeFunction<Dart_EnterIsolateNFT>>,
39-
Pointer<NativeFunction<Dart_ExitIsolateNFT>>,
40-
int)>('ThreadPoolTest_BarrierSync');
31+
Void Function(
32+
Pointer<NativeFunction<Dart_CurrentIsolateNFT>>,
33+
Pointer<NativeFunction<Dart_EnterIsolateNFT>>,
34+
Pointer<NativeFunction<Dart_ExitIsolateNFT>>,
35+
IntPtr,
36+
Bool,
37+
),
38+
void Function(
39+
Pointer<NativeFunction<Dart_CurrentIsolateNFT>>,
40+
Pointer<NativeFunction<Dart_EnterIsolateNFT>>,
41+
Pointer<NativeFunction<Dart_ExitIsolateNFT>>,
42+
int,
43+
bool,
44+
)
45+
>('ThreadPoolTest_BarrierSync');
4146

4247
final Pointer<NativeFunction<Dart_CurrentIsolateNFT>> dartCurrentIsolate =
4348
DynamicLibrary.executable().lookup("Dart_CurrentIsolate").cast();
@@ -51,8 +56,14 @@ class Worker extends RingElement {
5156
Worker(this.id);
5257

5358
Future run(dynamic _, dynamic _2) async {
59+
const bool exitAndReenterIsolate = true;
5460
threadPoolBarrierSync(
55-
dartCurrentIsolate, dartEnterIsolate, dartExitIsolate, threadCount);
61+
dartCurrentIsolate,
62+
dartEnterIsolate,
63+
dartExitIsolate,
64+
threadCount,
65+
exitAndReenterIsolate,
66+
);
5667
return id;
5768
}
5869
}

runtime/tests/vm/vm.status

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ dart/kernel_determinism_test: SkipSlow
5656
dart/minimal_kernel_test: SkipSlow # gen_kernel is too slow with optimization_counter_threshold
5757

5858
[ $compiler == app_jitk ]
59-
dart/isolates/many_isolates_blocked_at_ffi_test: Skip # App snapshot creation needs regular isolate shutdown
6059
dart/isolates/many_isolates_blocked_at_process_run_sync_test: Skip # App snapshot creation needs regular isolate shutdown
6160
dart/isolates/many_isolates_blocked_at_sleep_test: Skip # App snapshot creation needs regular isolate shutdown
6261
dart/snapshot_version_test: RuntimeError

tests/ffi/dl_api_exit_enter_isolate_test.dart

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,32 @@ final initializeApi = ffiTestFunctions.lookupFunction<
1616
int Function(Pointer<Void>)
1717
>("InitDartApiDL");
1818
final enterBarrier = ffiTestFunctions
19-
.lookupFunction<Void Function(IntPtr), void Function(int)>(
19+
.lookupFunction<Void Function(IntPtr, Bool), void Function(int, bool)>(
2020
"WaitUntilNThreadsEnterBarrier",
2121
);
2222

2323
main() async {
24+
initializeApi(NativeApi.initializeApiDLData);
25+
2426
const threadBarrierCount = 30;
2527

26-
initializeApi(NativeApi.initializeApiDLData);
28+
// The threads may explicitly decrease the mutator count by using
29+
// * Dart_ExitIsolate()
30+
// * block and
31+
// * Dart_EnterIsolate()
32+
await testNativeBarrier(threadBarrierCount, true);
33+
34+
// The threads may not explicitly exit the isolate but the VM may implicitly
35+
// (when entering an isolate for execution) kick other threads out of the
36+
// mutator count (by making them implicitly go to slow path when trying to
37+
// leave a safepoint).
38+
await testNativeBarrier(threadBarrierCount, false);
39+
}
2740

41+
Future testNativeBarrier(int count, bool exitAndReenterIsolate) async {
2842
final all = <Future>[];
29-
for (int i = 0; i < threadBarrierCount; ++i) {
30-
all.add(Isolate.run(() => enterBarrier(threadBarrierCount)));
43+
for (int i = 0; i < count; ++i) {
44+
all.add(Isolate.run(() => enterBarrier(count, true)));
3145
}
3246
await Future.wait(all);
3347
}

0 commit comments

Comments
 (0)