Untag and stop watch on network sockets before closing them.
am: 13e9518b53

Change-Id: I74dfec0bcff5f48a5580d6cef8994b521214baaa
diff --git a/libcurl_http_fetcher.cc b/libcurl_http_fetcher.cc
index 9dcd654..9d9f58b 100644
--- a/libcurl_http_fetcher.cc
+++ b/libcurl_http_fetcher.cc
@@ -68,6 +68,32 @@
 
 }  // namespace
 
+// static
+int LibcurlHttpFetcher::LibcurlCloseSocketCallback(void* clientp,
+                                                   curl_socket_t item) {
+#ifdef __ANDROID__
+  qtaguid_untagSocket(item);
+#endif  // __ANDROID__
+  LibcurlHttpFetcher* fetcher = static_cast<LibcurlHttpFetcher*>(clientp);
+  // Stop watching the socket before closing it.
+  for (size_t t = 0; t < arraysize(fetcher->fd_task_maps_); ++t) {
+    const auto fd_task_pair = fetcher->fd_task_maps_[t].find(item);
+    if (fd_task_pair != fetcher->fd_task_maps_[t].end()) {
+      if (!MessageLoop::current()->CancelTask(fd_task_pair->second)) {
+        LOG(WARNING) << "Error canceling the watch task "
+                     << fd_task_pair->second << " for "
+                     << (t ? "writing" : "reading") << " the fd " << item;
+      }
+      fetcher->fd_task_maps_[t].erase(item);
+    }
+  }
+
+  // Documentation for this callback says to return 0 on success or 1 on error.
+  if (!IGNORE_EINTR(close(item)))
+    return 0;
+  return 1;
+}
+
 LibcurlHttpFetcher::LibcurlHttpFetcher(ProxyResolver* proxy_resolver,
                                        HardwareInterface* hardware)
     : HttpFetcher(proxy_resolver), hardware_(hardware) {
@@ -126,9 +152,12 @@
   CHECK(curl_handle_);
   ignore_failure_ = false;
 
-  // Tag the socket for network usage stats.
+  // Tag and untag the socket for network usage stats.
   curl_easy_setopt(
       curl_handle_, CURLOPT_SOCKOPTFUNCTION, LibcurlSockoptCallback);
+  curl_easy_setopt(
+      curl_handle_, CURLOPT_CLOSESOCKETFUNCTION, LibcurlCloseSocketCallback);
+  curl_easy_setopt(curl_handle_, CURLOPT_CLOSESOCKETDATA, this);
 
   CHECK(HasProxy());
   bool is_direct = (GetCurrentProxy() == kNoProxy);
diff --git a/libcurl_http_fetcher.h b/libcurl_http_fetcher.h
index 5b16811..61871c9 100644
--- a/libcurl_http_fetcher.h
+++ b/libcurl_http_fetcher.h
@@ -107,6 +107,10 @@
   }
 
  private:
+  // libcurl's CURLOPT_CLOSESOCKETFUNCTION callback function. Called when
+  // closing a socket created with the CURLOPT_OPENSOCKETFUNCTION callback.
+  static int LibcurlCloseSocketCallback(void* clientp, curl_socket_t item);
+
   // Callback for when proxy resolution has completed. This begins the
   // transfer.
   void ProxiesResolved();