Stop leaking file descriptors for HTTP clients

Previously, we would wait for a Future to terminate before destroying
the underlying raw socket. If that future never terminated, we would
leak the underlying file descriptor.

Now, the "force" codepath in close destroys the socket immediately
(similar to what it did previously for active sockets) and the non-force
codepath has a timeout, as requested by a TODO comment.

Change-Id: I021a93a40e4708ce93b4f1ae6c3f7289764bd69f
Reviewed-on: https://dart-review.googlesource.com/54442
Reviewed-by: Zach Anderson <zra@google.com>
Commit-Queue: Adam Barth <abarth@google.com>
diff --git a/sdk/lib/_http/http_impl.dart b/sdk/lib/_http/http_impl.dart
index f2a025e..8061440 100644
--- a/sdk/lib/_http/http_impl.dart
+++ b/sdk/lib/_http/http_impl.dart
@@ -1766,8 +1766,7 @@
   void close() {
     closed = true;
     _httpClient._connectionClosed(this);
-    _streamFuture
-        // TODO(ajohnsen): Add timeout.
+    _streamFuture.timeout(_httpClient.idleTimeout)
         .then((_) => _socket.destroy());
   }
 
@@ -1885,13 +1884,17 @@
   }
 
   void close(bool force) {
-    for (var c in _idle.toList()) {
-      c.close();
-    }
     if (force) {
+      for (var c in _idle.toList()) {
+        c.destroy();
+      }
       for (var c in _active.toList()) {
         c.destroy();
       }
+    } else {
+      for (var c in _idle.toList()) {
+        c.close();
+      }
     }
   }