Skip to content

Commit 893e37a

Browse files
aamCommit Queue
authored andcommitted
[vm/shared] Add timeout to ConditionVariable.wait.
Update isolate_group_shared_callback_test to use that and also use flag to print exceptions. TEST=ci CoreLibraryReviewExempt: only internal library is affected Change-Id: Ia53ca7a6dc847b551229ccf00bbbfe302a260fcb Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/427680 Reviewed-by: Slava Egorov <[email protected]> Commit-Queue: Alexander Aprelev <[email protected]>
1 parent 77fa8cc commit 893e37a

File tree

6 files changed

+59
-27
lines changed

6 files changed

+59
-27
lines changed

runtime/bin/ffi_test/ffi_test_functions.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1342,7 +1342,7 @@ static void* Start(void* data_in) {
13421342
Data* data = reinterpret_cast<Data*>(data_in);
13431343
void (*fn)(int64_t, int32_t) = data->fn;
13441344
int64_t a = data->a;
1345-
int64_t b = data->b;
1345+
int32_t b = data->b;
13461346
delete data;
13471347
fn(a, b);
13481348
return nullptr;

runtime/lib/concurrent.cc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,8 @@ DEFINE_FFI_NATIVE_ENTRY(ConditionVariable_Initialize,
6767
DEFINE_FFI_NATIVE_ENTRY(ConditionVariable_Wait,
6868
void,
6969
(Dart_Handle condvar_handle,
70-
Dart_Handle mutex_handle)) {
70+
Dart_Handle mutex_handle,
71+
intptr_t timeout)) {
7172
Mutex* mutex;
7273
Dart_Handle result_mutex = Dart_GetNativeInstanceField(
7374
mutex_handle, kCondVarNativeField, reinterpret_cast<intptr_t*>(&mutex));
@@ -81,7 +82,7 @@ DEFINE_FFI_NATIVE_ENTRY(ConditionVariable_Wait,
8182
if (Dart_IsError(result_condvar)) {
8283
Dart_PropagateError(result_condvar);
8384
}
84-
condvar->Wait(mutex);
85+
condvar->Wait(mutex, timeout);
8586
}
8687

8788
DEFINE_FFI_NATIVE_ENTRY(ConditionVariable_Notify,

runtime/vm/bootstrap_natives.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,7 @@ namespace dart {
374374
V(ConditionVariable_Initialize, void, (Dart_Handle)) \
375375
V(ConditionVariable_Notify, void, (Dart_Handle)) \
376376
V(ConditionVariable_NotifyAll, void, (Dart_Handle)) \
377-
V(ConditionVariable_Wait, void, (Dart_Handle, Dart_Handle)) \
377+
V(ConditionVariable_Wait, void, (Dart_Handle, Dart_Handle, intptr_t)) \
378378
V(FinalizerEntry_SetExternalSize, void, (Dart_Handle, intptr_t)) \
379379
V(IsolateGroup_runSync, Dart_Handle, (Dart_Handle)) \
380380
V(Mutex_Initialize, void, (Dart_Handle)) \

sdk/lib/_internal/vm/lib/concurrent_patch.dart

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// BSD-style license that can be found in the LICENSE file.
44

55
import "dart:_internal" show patch;
6-
import "dart:ffi" show Handle, Void, Native;
6+
import "dart:ffi" show IntPtr, Handle, Native, Void;
77
import "dart:nativewrappers" show NativeFieldWrapperClass1;
88

99
@patch
@@ -47,8 +47,17 @@ base class _ConditionVariableImpl extends NativeFieldWrapperClass1
4747
@Native<Void Function(Handle)>(symbol: "ConditionVariable_Initialize")
4848
external void _initialize();
4949

50-
@Native<Void Function(Handle, Handle)>(symbol: "ConditionVariable_Wait")
51-
external void wait(Mutex mutex);
50+
@Native<Void Function(Handle, Handle, IntPtr)>(
51+
symbol: "ConditionVariable_Wait",
52+
)
53+
external void _wait(Mutex mutex, int timeout);
54+
55+
void wait(Mutex mutex, [int timeout = 0]) {
56+
if (timeout < 0) {
57+
throw ArgumentError.value(timeout, "timeout", "must be positive or zero");
58+
}
59+
_wait(mutex, timeout);
60+
}
5261

5362
@Native<Void Function(Handle)>(symbol: "ConditionVariable_Notify")
5463
external void notify();

sdk/lib/concurrent/concurrent.dart

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,13 @@ abstract interface class ConditionVariable {
4646
/// `mutex` must be a [Mutex] object exclusively held by the current thread.
4747
/// It will be released and the thread will block until another thread
4848
/// calls [notify].
49-
external void wait(Mutex mutex);
49+
///
50+
/// If `timeout` is provided, it must be positive or zero.
51+
/// Default zero value indicates that the method will wait to be notified
52+
/// infinitely, without timeout.
53+
/// If it is greater than zero, then after this many milliseconds the method
54+
/// will return even if the variable was not notified.
55+
external void wait(Mutex mutex, [int timeout = 0]);
5056

5157
/// Wake up at least one thread waiting on this condition variable.
5258
external void notify();

tests/ffi/isolate_group_shared_callback_test.dart

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,20 @@
44

55
// Dart test program for testing dart:ffi async callbacks.
66
//
7-
// VMOptions=--experimental-shared-data
8-
// VMOptions=--experimental-shared-data --use-slow-path
9-
// VMOptions=--experimental-shared-data --use-slow-path --stacktrace-every=100
10-
// VMOptions=--experimental-shared-data --dwarf_stack_traces --no-retain_function_objects --no-retain_code_objects
11-
// VMOptions=--experimental-shared-data --test_il_serialization
12-
// VMOptions=--experimental-shared-data --profiler --profile_vm=true
13-
// VMOptions=--experimental-shared-data --profiler --profile_vm=false
7+
// VMOptions=--experimental-shared-data --print-stacktrace-at-throw
8+
// VMOptions=--experimental-shared-data --print-stacktrace-at-throw --use-slow-path
9+
// VMOptions=--experimental-shared-data --print-stacktrace-at-throw --use-slow-path --stacktrace-every=100
10+
// VMOptions=--experimental-shared-data --print-stacktrace-at-throw --dwarf_stack_traces --no-retain_function_objects --no-retain_code_objects
11+
// VMOptions=--experimental-shared-data --print-stacktrace-at-throw --test_il_serialization
12+
// VMOptions=--experimental-shared-data --print-stacktrace-at-throw --profiler --profile_vm=true
13+
// VMOptions=--experimental-shared-data --print-stacktrace-at-throw --profiler --profile_vm=false
1414
// SharedObjects=ffi_test_functions
1515

1616
import 'dart:async';
1717
import 'dart:concurrent';
1818
import 'dart:ffi';
1919
import 'dart:isolate';
20+
import 'package:dart_internal/isolate_group.dart' show IsolateGroup;
2021

2122
import 'dart:io';
2223

@@ -45,14 +46,6 @@ class NativeLibrary {
4546
late final FnSleepType sleep;
4647

4748
NativeLibrary() {
48-
callFunctionOnSameThread = ffiTestFunctions
49-
.lookupFunction<FnRunnerNativeType, FnRunnerType>(
50-
"CallFunctionOnSameThread",
51-
);
52-
callFunctionOnNewThreadBlocking = ffiTestFunctions
53-
.lookupFunction<FnRunnerNativeType, FnRunnerType>(
54-
"CallFunctionOnNewThreadBlocking",
55-
);
5649
callFunctionOnNewThreadNonBlocking = ffiTestFunctions
5750
.lookupFunction<FnRunnerNativeType, FnRunnerType>(
5851
"CallFunctionOnNewThreadNonBlocking",
@@ -92,7 +85,6 @@ void simpleFunction(int a, int b) {
9285
Future<void> testNativeCallableHelloWorld() async {
9386
mutexCondvar = Mutex();
9487
conditionVariable = ConditionVariable();
95-
// final callback = NativeCallable<CallbackNativeType>.isolateGroupShared(simpleFunction);
9688
final callback = NativeCallable<CallbackNativeType>.isolateGroupShared(
9789
simpleFunction,
9890
);
@@ -103,7 +95,8 @@ Future<void> testNativeCallableHelloWorld() async {
10395

10496
mutexCondvar.runLocked(() {
10597
while (!resultIsReady) {
106-
conditionVariable.wait(mutexCondvar);
98+
conditionVariable.wait(mutexCondvar, 10 * sleepForMs);
99+
Expect.isTrue(resultIsReady);
107100
}
108101
});
109102

@@ -113,16 +106,38 @@ Future<void> testNativeCallableHelloWorld() async {
113106
lib.callFunctionOnNewThreadNonBlocking(1001, callback.nativeFunction);
114107
mutexCondvar.runLocked(() {
115108
while (!resultIsReady) {
116-
conditionVariable.wait(mutexCondvar);
109+
conditionVariable.wait(mutexCondvar, 10 * sleepForMs);
110+
Expect.isTrue(resultIsReady);
117111
}
118112
});
119113
Expect.equals(42 + (1001 * 123) * 2, result);
120114
}
121115

116+
void simpleFunctionThatThrows(int a, int b) {
117+
// Complete without notifying mutexCondvar
118+
throw 'hello, world';
119+
}
120+
121+
Future<void> testNativeCallableThrows() async {
122+
mutexCondvar = Mutex();
123+
conditionVariable = ConditionVariable();
124+
final callback = NativeCallable<CallbackNativeType>.isolateGroupShared(
125+
simpleFunctionThatThrows,
126+
);
127+
128+
result = 42;
129+
resultIsReady = false;
130+
lib.callFunctionOnNewThreadNonBlocking(1001, callback.nativeFunction);
131+
132+
mutexCondvar.runLocked(() {
133+
conditionVariable.wait(mutexCondvar, 10 * sleepForMs);
134+
Expect.isFalse(resultIsReady);
135+
});
136+
}
137+
122138
Future<void> testNativeCallableHelloWorldClosure() async {
123139
mutexCondvar = Mutex();
124140
conditionVariable = ConditionVariable();
125-
// final callback = NativeCallable<CallbackNativeType>.isolateGroupShared(simpleFunction);
126141
final callback = NativeCallable<CallbackNativeType>.isolateGroupShared((
127142
int a,
128143
int b,
@@ -213,6 +228,7 @@ main(args, message) async {
213228
lib = NativeLibrary();
214229
// Simple tests.
215230
await testNativeCallableHelloWorld();
231+
await testNativeCallableThrows();
216232
await testNativeCallableHelloWorldClosure();
217233
testNativeCallableSync();
218234
testNativeCallableSyncThrows();

0 commit comments

Comments
 (0)