[ffi/samples] Fix samples/ffi/http so it passes under tsan.
Before this fix running under tsan produces following warning:
```
00:00 +0: httpGet
00:03 +1: httpServe
00:04 +2: All tests passed!
/usr/bin/addr2line: DWARF error: mangled line number section (bad file number)
/usr/bin/addr2line: DWARF error: mangled line number section (bad file number)
/usr/bin/addr2line: DWARF error: mangled line number section (bad file number)
/usr/bin/addr2line: DWARF error: mangled line number section (bad file number)
/usr/bin/addr2line: DWARF error: mangled line number section (bad file number)
==================
WARNING: ThreadSanitizer: signal-unsafe call inside of a signal (pid=145964)
#0 malloc ../../../../../../llvm-llvm-project/../../../../../../llvm-llvm-project/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp:676 (dartvm+0x21c9330) (BuildId: d195bc5e9885ab144039c676e433289217750aec)
#1 __dcigettext intl/./intl/dcigettext.c:621 (libc.so.6+0x39f23) (BuildId: 4a95b54430cb5a2c68c1812f1738222660dec6d1)
#2 __tsan::CallUserSignalHandler(__tsan::ThreadState*, bool, bool, int, __sanitizer::__sanitizer_siginfo*, void*) ../../../../../../llvm-llvm-project/../../../../../../llvm-llvm-project/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp:2149 (dartvm+0x21d34af) (BuildId: d195bc5e9885ab144039c676e433289217750aec)
SUMMARY: ThreadSanitizer: signal-unsafe call inside of a signal intl/./intl/dcigettext.c:621 in __dcigettext
==================
ThreadSanitizer: reported 1 warnings
```
TEST=samples/ffi/http
Change-Id: I4cd1b62d30cde3ff0d4cd5f6a23c33e36491884a
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/445284
Commit-Queue: Alexander Aprelev <aam@google.com>
Reviewed-by: Liam Appelbe <liama@google.com>
This commit is contained in:
committed by
Commit Queue
parent
aa4d2350c9
commit
11399713c5
@@ -38,11 +38,23 @@ DART_EXPORT void http_get(const char* uri, void (*onResponse)(const char*)) {
|
||||
}).detach();
|
||||
}
|
||||
|
||||
DART_EXPORT void http_serve(void (*onRequest)(const char*)) {
|
||||
std::thread([onRequest]() {
|
||||
while (true) {
|
||||
std::atomic<bool> stop_requested = false;
|
||||
std::thread* server = nullptr;
|
||||
|
||||
DART_EXPORT void http_start_serving(void (*onRequest)(const char*)) {
|
||||
server = new std::thread([onRequest]() {
|
||||
while (!stop_requested) {
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
onRequest(kExampleRequest);
|
||||
}
|
||||
}).detach();
|
||||
});
|
||||
}
|
||||
|
||||
DART_EXPORT void http_stop_serving() {
|
||||
if (server != nullptr) {
|
||||
stop_requested = true;
|
||||
server->join();
|
||||
delete server;
|
||||
server = nullptr;
|
||||
}
|
||||
}
|
||||
@@ -39,7 +39,8 @@ Future<String> httpGet(String uri) async {
|
||||
}
|
||||
|
||||
// Start a HTTP server on a background thread.
|
||||
void httpServe(void Function(String) onRequest) {
|
||||
// Returns a function that should be called to stop the server.
|
||||
Function httpServe(void Function(String) onRequest) {
|
||||
// Create the NativeCallable.listener.
|
||||
void onNativeRequest(Pointer<Utf8> requestPointer) {
|
||||
onRequest(requestPointer.toDartString());
|
||||
@@ -50,13 +51,12 @@ void httpServe(void Function(String) onRequest) {
|
||||
// Invoke the native function to start the HTTP server. Our example
|
||||
// HTTP library will start a server on a background thread, and pass
|
||||
// any requests it receives to out callback.
|
||||
nativeHttpServe(callback.nativeFunction);
|
||||
nativeHttpStartServing(callback.nativeFunction);
|
||||
|
||||
// The server will run indefinitely, and the callback needs to stay
|
||||
// alive for that whole time, so we can't close the callback here.
|
||||
// But we also don't want the callback to keep the isolate alive
|
||||
// forever, so we set keepIsolateAlive to false.
|
||||
callback.keepIsolateAlive = false;
|
||||
return () {
|
||||
nativeHttpStopServing();
|
||||
callback.close();
|
||||
};
|
||||
}
|
||||
|
||||
// Load the native functions from a DynamicLibrary.
|
||||
@@ -73,12 +73,21 @@ typedef HttpGetNativeFunction = Void Function(
|
||||
final nativeHttpGet =
|
||||
dylib.lookupFunction<HttpGetNativeFunction, HttpGetFunction>('http_get');
|
||||
|
||||
typedef HttpServeFunction = void Function(
|
||||
typedef HttpStartServingFunction = bool Function(
|
||||
Pointer<NativeFunction<HttpCallback>>);
|
||||
typedef HttpServeNativeFunction = Void Function(
|
||||
typedef HttpStartServingNativeFunction = Bool Function(
|
||||
Pointer<NativeFunction<HttpCallback>>);
|
||||
final nativeHttpServe = dylib
|
||||
.lookupFunction<HttpServeNativeFunction, HttpServeFunction>('http_serve');
|
||||
final nativeHttpStartServing = dylib
|
||||
.lookupFunction<HttpStartServingNativeFunction, HttpStartServingFunction>(
|
||||
'http_start_serving',
|
||||
);
|
||||
|
||||
typedef HttpStopServingFunction = void Function();
|
||||
typedef HttpStopServingNativeFunction = Void Function();
|
||||
final nativeHttpStopServing = dylib
|
||||
.lookupFunction<HttpStopServingNativeFunction, HttpStopServingFunction>(
|
||||
'http_stop_serving',
|
||||
);
|
||||
|
||||
Future<void> main() async {
|
||||
print('Sending GET request...');
|
||||
|
||||
@@ -16,12 +16,13 @@ Future<void> main() async {
|
||||
|
||||
test('httpServe', () async {
|
||||
final completer = Completer<String>();
|
||||
httpServe((request) {
|
||||
final callWhenDone = httpServe((request) {
|
||||
if (!completer.isCompleted) {
|
||||
completer.complete(request);
|
||||
}
|
||||
});
|
||||
final request = await completer.future;
|
||||
expect(request, contains('www.example.com'));
|
||||
callWhenDone();
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user