Use --oat-fd instead of --oat-file when calling dex2oat.
This way we avoid forking and execing dex2oat if the output oat file
is not writeable, and the error messages are slightly better.
Bug: 19937016
Change-Id: I2320f70aa37653b85df40fe1977e09f33789cb8b
diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc
index 8d5418d..99080f6 100644
--- a/runtime/oat_file_assistant.cc
+++ b/runtime/oat_file_assistant.cc
@@ -662,6 +662,13 @@
bool OatFileAssistant::GenerateOatFile(std::string* error_msg) {
CHECK(error_msg != nullptr);
+ Runtime* runtime = Runtime::Current();
+ if (!runtime->IsDex2OatEnabled()) {
+ *error_msg = "Generation of oat file for dex location " + dex_location_
+ + " not attempted because dex2oat is disabled.";
+ return false;
+ }
+
if (OatFileName() == nullptr) {
*error_msg = "Generation of oat file for dex location " + dex_location_
+ " not attempted because the oat file name could not be determined.";
@@ -669,17 +676,6 @@
}
const std::string& oat_file_name = *OatFileName();
- Runtime* runtime = Runtime::Current();
- if (!runtime->IsDex2OatEnabled()) {
- *error_msg = "Generation of oat file " + oat_file_name
- + " not attempted because dex2oat is disabled";
- return false;
- }
-
- std::vector<std::string> args;
- args.push_back("--dex-file=" + dex_location_);
- args.push_back("--oat-file=" + oat_file_name);
-
// dex2oat ignores missing dex files and doesn't report an error.
// Check explicitly here so we can detect the error properly.
// TODO: Why does dex2oat behave that way?
@@ -688,9 +684,36 @@
return false;
}
+ std::unique_ptr<File> oat_file;
+ oat_file.reset(OS::CreateEmptyFile(oat_file_name.c_str()));
+ if (oat_file.get() == nullptr) {
+ *error_msg = "Generation of oat file " + oat_file_name
+ + " not attempted because the oat file could not be created.";
+ return false;
+ }
+
+ if (fchmod(oat_file->Fd(), 0644) != 0) {
+ *error_msg = "Generation of oat file " + oat_file_name
+ + " not attempted because the oat file could not be made world readable.";
+ oat_file->Erase();
+ return false;
+ }
+
+ std::vector<std::string> args;
+ args.push_back("--dex-file=" + dex_location_);
+ args.push_back("--oat-fd=" + std::to_string(oat_file->Fd()));
+ args.push_back("--oat-location=" + oat_file_name);
+
if (!Dex2Oat(args, error_msg)) {
// Manually delete the file. This ensures there is no garbage left over if
// the process unexpectedly died.
+ oat_file->Erase();
+ TEMP_FAILURE_RETRY(unlink(oat_file_name.c_str()));
+ return false;
+ }
+
+ if (oat_file->FlushCloseOrErase() != 0) {
+ *error_msg = "Unable to close oat file " + oat_file_name;
TEMP_FAILURE_RETRY(unlink(oat_file_name.c_str()));
return false;
}