Make unit tests less timing sensitive when unmounting busy loop devices.

This CL modifies utils::UnmountFilesystem() to retry when umount()
fails to unmount a busy loop device and replaces several unit tests to
use the modified utils::UnmountFilesystem() instead of calling
System("umount").

BUG=chromium-os:35112
TEST=Run unit tests repeatedly.

Change-Id: I42978f02b4797c68acbec6c351ea2663b9ec7b59
Reviewed-on: https://gerrit.chromium.org/gerrit/34862
Reviewed-by: Ben Chan <benchan@chromium.org>
Tested-by: Ben Chan <benchan@chromium.org>
Commit-Ready: Ben Chan <benchan@chromium.org>
diff --git a/utils.cc b/utils.cc
index e0d9244..1e87262 100644
--- a/utils.cc
+++ b/utils.cc
@@ -41,6 +41,16 @@
 
 namespace chromeos_update_engine {
 
+namespace {
+
+// The following constants control how UnmountFilesystem should retry if
+// umount() fails with an errno EBUSY, i.e. retry 5 times over the course of
+// one second.
+const int kUnmountMaxNumOfRetries = 5;
+const int kUnmountRetryIntervalInMicroseconds = 200 * 1000;  // 200 ms
+
+}  // namespace
+
 namespace utils {
 
 static const char kDevImageMarker[] = "/root/.dev_mode";
@@ -497,7 +507,14 @@
 }
 
 bool UnmountFilesystem(const string& mountpoint) {
-  TEST_AND_RETURN_FALSE_ERRNO(umount(mountpoint.c_str()) == 0);
+  for (int num_retries = 0; ; ++num_retries) {
+    if (umount(mountpoint.c_str()) == 0)
+      break;
+
+    TEST_AND_RETURN_FALSE_ERRNO(errno == EBUSY &&
+                                num_retries < kUnmountMaxNumOfRetries);
+    usleep(kUnmountRetryIntervalInMicroseconds);
+  }
   return true;
 }