diff options
| -rw-r--r-- | runtime/oat_file_assistant.cc | 45 | ||||
| -rw-r--r-- | runtime/oat_file_assistant_test.cc | 32 |
2 files changed, 66 insertions, 11 deletions
diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc index 8d5418d07d..99080f611c 100644 --- a/runtime/oat_file_assistant.cc +++ b/runtime/oat_file_assistant.cc @@ -662,23 +662,19 @@ bool OatFileAssistant::RelocateOatFile(const std::string* input_file, bool OatFileAssistant::GenerateOatFile(std::string* error_msg) { CHECK(error_msg != nullptr); - if (OatFileName() == nullptr) { + Runtime* runtime = Runtime::Current(); + if (!runtime->IsDex2OatEnabled()) { *error_msg = "Generation of oat file for dex location " + dex_location_ - + " not attempted because the oat file name could not be determined."; + + " not attempted because dex2oat is disabled."; return false; } - 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"; + 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."; return false; } - - std::vector<std::string> args; - args.push_back("--dex-file=" + dex_location_); - args.push_back("--oat-file=" + oat_file_name); + const std::string& oat_file_name = *OatFileName(); // dex2oat ignores missing dex files and doesn't report an error. // Check explicitly here so we can detect the error properly. @@ -688,9 +684,36 @@ bool OatFileAssistant::GenerateOatFile(std::string* error_msg) { 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; } diff --git a/runtime/oat_file_assistant_test.cc b/runtime/oat_file_assistant_test.cc index 2c81eddf39..c54d7f8761 100644 --- a/runtime/oat_file_assistant_test.cc +++ b/runtime/oat_file_assistant_test.cc @@ -849,6 +849,38 @@ TEST_F(OatFileAssistantTest, LoadDexNoAlternateOat) { EXPECT_FALSE(ofm.OatFileExists()); } +// Case: We have a DEX file but can't write the oat file. +// Expect: We should fail to make the oat file up to date. +TEST_F(OatFileAssistantTest, LoadDexUnwriteableAlternateOat) { + std::string dex_location = GetScratchDir() + "/LoadDexUnwriteableAlternateOat.jar"; + + // Make the oat location unwritable by inserting some non-existent + // intermediate directories. + std::string oat_location = GetScratchDir() + "/foo/bar/LoadDexUnwriteableAlternateOat.oat"; + + Copy(GetDexSrc1(), dex_location); + + OatFileAssistant oat_file_assistant( + dex_location.c_str(), oat_location.c_str(), kRuntimeISA, true); + std::string error_msg; + ASSERT_FALSE(oat_file_assistant.MakeUpToDate(&error_msg)); + + std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); + ASSERT_TRUE(oat_file.get() == nullptr); +} + +// Case: We don't have a DEX file and can't write the oat file. +// Expect: We should fail to generate the oat file without crashing. +TEST_F(OatFileAssistantTest, GenNoDex) { + std::string dex_location = GetScratchDir() + "/GenNoDex.jar"; + std::string oat_location = GetScratchDir() + "/GenNoDex.oat"; + + OatFileAssistant oat_file_assistant( + dex_location.c_str(), oat_location.c_str(), kRuntimeISA, true); + std::string error_msg; + ASSERT_FALSE(oat_file_assistant.GenerateOatFile(&error_msg)); +} + // Turn an absolute path into a path relative to the current working // directory. static std::string MakePathRelative(std::string target) { |