ART: Track Flush & Close in FdFile

Implement a check that aborts when a file hasn't been explicitly
flushed and closed when it is destructed.

Add WARN_UNUSED to FdFile methods.

Update dex2oat, patchoat, scoped_flock and some gtests to pass with
this.

(cherry picked from commit 9433ec60b325b708b9fa87e699ab4a6565741494)

Change-Id: I9ab03b1653e69f44cc98946dc89d764c3e045dd4
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 2d2a82e..927c5f5 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -942,9 +942,11 @@
         oat_location_ = oat_filename_;
       }
     } else {
-      oat_file_.reset(new File(oat_fd_, oat_location_));
+      oat_file_.reset(new File(oat_fd_, oat_location_, true));
       oat_file_->DisableAutoClose();
-      oat_file_->SetLength(0);
+      if (oat_file_->SetLength(0) != 0) {
+        PLOG(WARNING) << "Truncating oat file " << oat_location_ << " failed.";
+      }
     }
     if (oat_file_.get() == nullptr) {
       PLOG(ERROR) << "Failed to create oat file: " << oat_location_;
@@ -952,6 +954,7 @@
     }
     if (create_file && fchmod(oat_file_->Fd(), 0644) != 0) {
       PLOG(ERROR) << "Failed to make oat file world readable: " << oat_location_;
+      oat_file_->Erase();
       return false;
     }
     return true;
@@ -1075,7 +1078,10 @@
                 << ". Try: adb shell chmod 777 /data/local/tmp";
             continue;
           }
-          tmp_file->WriteFully(dex_file->Begin(), dex_file->Size());
+          // This is just dumping files for debugging. Ignore errors, and leave remnants.
+          UNUSED(tmp_file->WriteFully(dex_file->Begin(), dex_file->Size()));
+          UNUSED(tmp_file->Flush());
+          UNUSED(tmp_file->Close());
           LOG(INFO) << "Wrote input to " << tmp_file_name;
         }
       }
@@ -1266,6 +1272,7 @@
       if (!driver_->WriteElf(android_root_, is_host_, dex_files_, oat_writer.get(),
                              oat_file_.get())) {
         LOG(ERROR) << "Failed to write ELF file " << oat_file_->GetPath();
+        oat_file_->Erase();
         return false;
       }
     }
@@ -1273,8 +1280,8 @@
     // Flush result to disk.
     {
       TimingLogger::ScopedTiming t2("dex2oat Flush ELF", timings_);
-      if (oat_file_->Flush() != 0) {
-        LOG(ERROR) << "Failed to flush ELF file " << oat_file_->GetPath();
+      if (oat_file_->FlushCloseOrErase() != 0) {
+        PLOG(ERROR) << "Failed to flush ELF file " << oat_file_->GetPath();
         return false;
       }
     }
@@ -1302,7 +1309,13 @@
     // We need to strip after image creation because FixupElf needs to use .strtab.
     if (oat_unstripped_ != oat_stripped_) {
       TimingLogger::ScopedTiming t("dex2oat OatFile copy", timings_);
-      oat_file_.reset();
+      if (kUsePortableCompiler) {
+        if (oat_file_->FlushCloseOrErase() != 0) {
+          PLOG(ERROR) << "Failed to flush and close oat file: " << oat_location_;
+          return EXIT_FAILURE;
+        }
+        oat_file_.reset();
+      }
       std::unique_ptr<File> in(OS::OpenFileForReading(oat_unstripped_.c_str()));
       std::unique_ptr<File> out(OS::CreateEmptyFile(oat_stripped_.c_str()));
       size_t buffer_size = 8192;
@@ -1330,6 +1343,7 @@
         std::string error_msg;
         if (!ElfFile::Strip(oat_file_.get(), &error_msg)) {
           LOG(ERROR) << "Failed to strip elf file: " << error_msg;
+          oat_file_->Erase();
           return false;
         }
 
@@ -1338,8 +1352,20 @@
       } else {
         VLOG(compiler) << "Oat file written successfully without stripping: " << oat_location_;
       }
+      if (oat_file_->FlushCloseOrErase() != 0) {
+        PLOG(ERROR) << "Failed to flush and close oat file: " << oat_location_;
+        return EXIT_FAILURE;
+      }
+      oat_file_.reset(nullptr);
     }
 
+    if (oat_file_.get() != nullptr) {
+      if (oat_file_->FlushCloseOrErase() != 0) {
+        PLOG(ERROR) << "Failed to flush and close oat file: " << oat_location_ << "/"
+                    << oat_filename_;
+        return EXIT_FAILURE;
+      }
+    }
     return true;
   }
 
@@ -1451,18 +1477,24 @@
     // Destroy ImageWriter before doing FixupElf.
     image_writer_.reset();
 
-    std::unique_ptr<File> oat_file(OS::OpenFileReadWrite(oat_unstripped_.c_str()));
-    if (oat_file.get() == nullptr) {
-      PLOG(ERROR) << "Failed to open ELF file: " << oat_unstripped_;
-      return false;
-    }
-
     // Do not fix up the ELF file if we are --compile-pic
     if (!compiler_options_->GetCompilePic()) {
+      std::unique_ptr<File> oat_file(OS::OpenFileReadWrite(oat_unstripped_.c_str()));
+      if (oat_file.get() == nullptr) {
+        PLOG(ERROR) << "Failed to open ELF file: " << oat_unstripped_;
+        return false;
+      }
+
       if (!ElfWriter::Fixup(oat_file.get(), oat_data_begin)) {
+        oat_file->Erase();
         LOG(ERROR) << "Failed to fixup ELF file " << oat_file->GetPath();
         return false;
       }
+
+      if (oat_file->FlushCloseOrErase()) {
+        PLOG(ERROR) << "Failed to flush and close fixed ELF file " << oat_file->GetPath();
+        return false;
+      }
     }
 
     return true;