Fix opening oat files that are out of date.

Make sure we're not using an old MAP_PRIVATE mapping of an
OatFile after a forked process modifies the underlying file.

Change-Id: I5c6caaf34272c805e40e95ee690dd948d7406751
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 131ebf8..b1117a2 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -540,7 +540,8 @@
 
 bool ClassLinker::GenerateOatFile(const char* dex_filename,
                                   int oat_fd,
-                                  const char* oat_cache_filename) {
+                                  const char* oat_cache_filename,
+                                  std::string* error_msg) {
   Locks::mutator_lock_->AssertNotHeld(Thread::Current());  // Avoid starving GC.
   std::string dex2oat_string(GetAndroidRoot());
   dex2oat_string += (kIsDebugBuild ? "/bin/dex2oatd" : "/bin/dex2oat");
@@ -633,15 +634,13 @@
     int status;
     pid_t got_pid = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));
     if (got_pid != pid) {
-      ScopedObjectAccess soa(Thread::Current());
-      ThrowIOException("Failed to create oat file. Waitpid failed: wanted %d, got %d", pid,
-                       got_pid);
+      *error_msg = StringPrintf("Failed to create oat file. Waitpid failed: wanted %d, got %d",
+                                pid, got_pid);
       return false;
     }
     if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
-      ScopedObjectAccess soa(Thread::Current());
-      ThrowIOException("Failed to create oat file. %s failed with dex-file '%s'", dex2oat,
-                       dex_filename);
+      *error_msg = StringPrintf("Failed to create oat file. %s failed with dex-file '%s'",
+                                dex2oat, dex_filename);
       return false;
     }
   }
@@ -827,10 +826,24 @@
       << oat_location << "': " << *error_msg;
   error_msg->clear();
 
+  {
+    // We might have registered an outdated OatFile in FindDexFileInOatLocation().
+    // Get rid of it as its MAP_PRIVATE mapping may not reflect changes we're about to do.
+    WriterMutexLock mu(Thread::Current(), dex_lock_);
+    for (size_t i = 0; i < oat_files_.size(); ++i) {
+      if (oat_location == oat_files_[i]->GetLocation()) {
+        VLOG(class_linker) << "De-registering old OatFile: " << oat_location;
+        delete oat_files_[i];
+        oat_files_.erase(oat_files_.begin() + i);
+        break;
+      }
+    }
+  }
+
   // Generate the output oat file for the dex file
   VLOG(class_linker) << "Generating oat file " << oat_location << " for " << dex_location;
-  if (!GenerateOatFile(dex_location, scoped_flock.GetFile().Fd(), oat_location)) {
-    CHECK(Thread::Current()->IsExceptionPending());
+  if (!GenerateOatFile(dex_location, scoped_flock.GetFile().Fd(), oat_location, error_msg)) {
+    CHECK(!error_msg->empty());
     return nullptr;
   }
   const OatFile* oat_file = OatFile::Open(oat_location, oat_location, NULL,