shill: WiFi: Do not crash on RemoveNetwork failure

The failure of this call should not cause shill to crash when
called from DisconnectFrom().  It can happen during system
shutdown when shill and wpa_supplicant race to shut down.
wpa_supplicant's DBus endpoint could disappear just after we
enter the shill exit handler.

BUG=chromium-os:33658
TEST=Rerun unit tests.  MatFunc 000

Change-Id: I21d599cdc495e0d1246d450306847c0a8be752c7
Reviewed-on: https://gerrit.chromium.org/gerrit/33231
Reviewed-by: mukesh agrawal <quiche@chromium.org>
Commit-Ready: Paul Stewart <pstew@chromium.org>
Tested-by: Paul Stewart <pstew@chromium.org>
diff --git a/supplicant_interface_proxy.cc b/supplicant_interface_proxy.cc
index 807ccf0..ad581a2 100644
--- a/supplicant_interface_proxy.cc
+++ b/supplicant_interface_proxy.cc
@@ -92,7 +92,8 @@
   try {
     return proxy_.RemoveNetwork(network);
   } catch (const DBus::Error &e) {
-    LOG(FATAL) << "DBus exception: " << e.name() << ": " << e.what();
+    LOG(ERROR) << "DBus exception: " << e.name() << ": " << e.what();
+    throw;  // Re-throw the exception.
   }
 }
 
diff --git a/wifi.cc b/wifi.cc
index 8ff1e78..f32d12d 100644
--- a/wifi.cc
+++ b/wifi.cc
@@ -381,7 +381,7 @@
                    << service->friendly_name() << ": "
                    << "could not find supplicant network to disable.";
     } else {
-      supplicant_interface_proxy_->RemoveNetwork(rpcid_it->second);
+      RemoveNetwork(rpcid_it->second);
     }
     current_service_ = NULL;
   }
@@ -390,6 +390,15 @@
         current_service_.get() != pending_service_.get());
 }
 
+bool WiFi::RemoveNetwork(const ::DBus::Path &network) {
+  try {
+    supplicant_interface_proxy_->RemoveNetwork(network);
+  } catch (const DBus::Error &e) {  // NOLINT
+    return false;
+  }
+  return true;
+}
+
 bool WiFi::IsIdle() const {
   return !current_service_ && !pending_service_;
 }
@@ -592,7 +601,9 @@
   } else {
     // TODO(quiche): Reconsider giving up immediately. Maybe give
     // wpa_supplicant some time to retry, first.
-    supplicant_interface_proxy_->RemoveNetwork(rpcid_it->second);
+    if (!RemoveNetwork(rpcid_it->second)) {
+      LOG(FATAL) << "RemoveNetwork for " << rpcid_it->second << " failed.";
+    }
   }
 
   SLOG(WiFi, 2) << "WiFi " << link_name() << " disconnected from "
diff --git a/wifi.h b/wifi.h
index a5baa1a..49b97f0 100644
--- a/wifi.h
+++ b/wifi.h
@@ -253,6 +253,9 @@
       uint16(WiFi::*get)(Error *error),
       void(WiFi::*set)(const uint16 &value, Error *error));
 
+  // Remove a network entry from wpa_supplicant, and catch any exception
+  // that occurs.  Returns false if an exception occurred, true otherwise.
+  bool RemoveNetwork(const ::DBus::Path &network);
   // Restart fast scanning after disconnection.
   void RestartFastScanAttempts();
   // Schedules a scan attempt at time |scan_interval_seconds_| in the