[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>
diff --git a/samples/ffi/http/lib/fake_http.cc b/samples/ffi/http/lib/fake_http.cc
index 63b4f1d..4420e5e 100644
--- a/samples/ffi/http/lib/fake_http.cc
+++ b/samples/ffi/http/lib/fake_http.cc
@@ -38,11 +38,23 @@
   }).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;
+  }
+}
\ No newline at end of file
diff --git a/samples/ffi/http/lib/http.dart b/samples/ffi/http/lib/http.dart
index 0ce55c2..850d80d 100644
--- a/samples/ffi/http/lib/http.dart
+++ b/samples/ffi/http/lib/http.dart
@@ -39,7 +39,8 @@
 }
 
 // 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 @@
   // 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 @@
 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...');
diff --git a/samples/ffi/http/test/http_test.dart b/samples/ffi/http/test/http_test.dart
index 56b092b..c43ab99 100644
--- a/samples/ffi/http/test/http_test.dart
+++ b/samples/ffi/http/test/http_test.dart
@@ -16,12 +16,13 @@
 
   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();
   });
 }