am 3e78664f: am f8dc6489: am 7571e8b7: Add flock(2)ing on dex-cache files to prevent races
* commit '3e78664ffa63f3a01b0769a57409933a82648b4a':
Add flock(2)ing on dex-cache files to prevent races
diff --git a/compiler/elf_writer_test.cc b/compiler/elf_writer_test.cc
index e48806e..ffe1f72 100644
--- a/compiler/elf_writer_test.cc
+++ b/compiler/elf_writer_test.cc
@@ -62,7 +62,7 @@
ASSERT_EQ(0, dlclose(dl_oat_so));
- UniquePtr<File> file(OS::OpenFile(elf_filename.c_str(), false));
+ UniquePtr<File> file(OS::OpenFileForReading(elf_filename.c_str()));
ASSERT_TRUE(file.get() != NULL);
{
UniquePtr<ElfFile> ef(ElfFile::Open(file.get(), false, false));
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
index a40e3fc..4e9ae54 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -79,7 +79,7 @@
dex_caches_.insert(dex_cache);
}
- UniquePtr<File> oat_file(OS::OpenFile(oat_filename.c_str(), true, false));
+ UniquePtr<File> oat_file(OS::OpenFileReadWrite(oat_filename.c_str()));
if (oat_file.get() == NULL) {
LOG(ERROR) << "Failed to open oat file " << oat_filename << " for " << oat_location;
return false;
@@ -145,7 +145,7 @@
PatchOatCodeAndMethods();
Thread::Current()->TransitionFromRunnableToSuspended(kNative);
- UniquePtr<File> image_file(OS::OpenFile(image_filename.c_str(), true));
+ UniquePtr<File> image_file(OS::CreateEmptyFile(image_filename.c_str()));
if (image_file.get() == NULL) {
LOG(ERROR) << "Failed to open image file " << image_filename;
return false;
diff --git a/compiler/llvm/llvm_compilation_unit.cc b/compiler/llvm/llvm_compilation_unit.cc
index 9296fc7..aa439cc 100644
--- a/compiler/llvm/llvm_compilation_unit.cc
+++ b/compiler/llvm/llvm_compilation_unit.cc
@@ -155,7 +155,7 @@
std::string bitcode;
DumpBitcodeToString(bitcode);
std::string filename(StringPrintf("%s/Art%u.bc", DumpDirectory().c_str(), cunit_id_));
- UniquePtr<File> output(OS::OpenFile(filename.c_str(), true));
+ UniquePtr<File> output(OS::CreateEmptyFile(filename.c_str()));
output->WriteFully(bitcode.data(), bitcode.size());
LOG(INFO) << ".bc file written successfully: " << filename;
}
@@ -182,7 +182,7 @@
if (kDumpELF) {
// Dump the ELF image for debugging
std::string filename(StringPrintf("%s/Art%u.o", DumpDirectory().c_str(), cunit_id_));
- UniquePtr<File> output(OS::OpenFile(filename.c_str(), true));
+ UniquePtr<File> output(OS::CreateEmptyFile(filename.c_str()));
output->WriteFully(elf_object_.data(), elf_object_.size());
LOG(INFO) << ".o file written successfully: " << filename;
}
diff --git a/compiler/sea_ir/debug/dot_gen.h b/compiler/sea_ir/debug/dot_gen.h
index 675d83d..5270582 100644
--- a/compiler/sea_ir/debug/dot_gen.h
+++ b/compiler/sea_ir/debug/dot_gen.h
@@ -103,7 +103,7 @@
LOG(INFO) << "Starting to write SEA string to file.";
DotGenerationVisitor dgv = DotGenerationVisitor(&options_, types);
graph->Accept(&dgv);
- art::File* file = art::OS::OpenFile(filename.c_str(), true, true);
+ art::File* file = art::OS::OpenFile(filename.c_str(), O_RDWR | O_CREAT | O_TRUNC);
art::FileOutputStream fos(file);
std::string graph_as_string = dgv.GetResult();
graph_as_string += "}";
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 25cfda6..ceb6bf6 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -313,7 +313,7 @@
oat_data_begin = image_writer.GetOatDataBegin();
}
- UniquePtr<File> oat_file(OS::OpenFile(oat_filename.c_str(), true, false));
+ UniquePtr<File> oat_file(OS::OpenFileReadWrite(oat_filename.c_str()));
if (oat_file.get() == NULL) {
PLOG(ERROR) << "Failed to open ELF file: " << oat_filename;
return false;
@@ -808,7 +808,7 @@
UniquePtr<File> oat_file;
bool create_file = !oat_unstripped.empty(); // as opposed to using open file descriptor
if (create_file) {
- oat_file.reset(OS::OpenFile(oat_unstripped.c_str(), true));
+ oat_file.reset(OS::CreateEmptyFile(oat_unstripped.c_str()));
if (oat_location.empty()) {
oat_location = oat_filename;
}
@@ -1023,8 +1023,8 @@
if (oat_unstripped != oat_stripped) {
timings.NewSplit("dex2oat OatFile copy");
oat_file.reset();
- UniquePtr<File> in(OS::OpenFile(oat_unstripped.c_str(), false));
- UniquePtr<File> out(OS::OpenFile(oat_stripped.c_str(), true));
+ UniquePtr<File> in(OS::OpenFileForReading(oat_unstripped.c_str()));
+ UniquePtr<File> out(OS::CreateEmptyFile(oat_stripped.c_str()));
size_t buffer_size = 8192;
UniquePtr<uint8_t> buffer(new uint8_t[buffer_size]);
while (true) {
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index 67398af..fbfdfd9 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -777,7 +777,7 @@
os_ = saved_os;
}
os << "STATS:\n" << std::flush;
- UniquePtr<File> file(OS::OpenFile(image_filename_.c_str(), false));
+ UniquePtr<File> file(OS::OpenFileForReading(image_filename_.c_str()));
stats_.file_bytes = file->GetLength();
size_t header_bytes = sizeof(ImageHeader);
stats_.header_bytes = header_bytes;
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index bd36a6c..039e7bc 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -659,6 +659,7 @@
CHECK_NE(&oat_file, oat_files_[i]) << oat_file.GetLocation();
}
}
+ VLOG(class_linker) << "Registering " << oat_file.GetLocation();
oat_files_.push_back(&oat_file);
}
@@ -694,22 +695,39 @@
UniquePtr<OatFile> oat_file(OatFile::Open(oat_location, oat_location, NULL,
!Runtime::Current()->IsCompiler()));
if (oat_file.get() == NULL) {
+ VLOG(class_linker) << "Failed to find existing oat file at " << oat_location;
return NULL;
}
Runtime* runtime = Runtime::Current();
const ImageHeader& image_header = runtime->GetHeap()->GetImageSpace()->GetImageHeader();
- if (oat_file->GetOatHeader().GetImageFileLocationOatChecksum() != image_header.GetOatChecksum()) {
+ uint32_t expected_image_oat_checksum = image_header.GetOatChecksum();
+ uint32_t actual_image_oat_checksum = oat_file->GetOatHeader().GetImageFileLocationOatChecksum();
+ if (expected_image_oat_checksum != actual_image_oat_checksum) {
+ VLOG(class_linker) << "Failed to find oat file at " << oat_location
+ << " with expected image oat checksum of " << expected_image_oat_checksum
+ << ", found " << actual_image_oat_checksum;
return NULL;
}
- if (oat_file->GetOatHeader().GetImageFileLocationOatDataBegin()
- != reinterpret_cast<uint32_t>(image_header.GetOatDataBegin())) {
+
+ uint32_t expected_image_oat_offset = reinterpret_cast<uint32_t>(image_header.GetOatDataBegin());
+ uint32_t actual_image_oat_offset = oat_file->GetOatHeader().GetImageFileLocationOatDataBegin();
+ if (expected_image_oat_offset != actual_image_oat_offset) {
+ VLOG(class_linker) << "Failed to find oat file at " << oat_location
+ << " with expected image oat offset " << expected_image_oat_offset
+ << ", found " << actual_image_oat_offset;
return NULL;
}
const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_location);
if (oat_dex_file == NULL) {
+ VLOG(class_linker) << "Failed to find oat file at " << oat_location << " containing " << dex_location;
return NULL;
}
- if (oat_dex_file->GetDexFileLocationChecksum() != dex_location_checksum) {
+ uint32_t expected_dex_checksum = dex_location_checksum;
+ uint32_t actual_dex_checksum = oat_dex_file->GetDexFileLocationChecksum();
+ if (expected_dex_checksum != actual_dex_checksum) {
+ VLOG(class_linker) << "Failed to find oat file at " << oat_location
+ << " with expected dex checksum of " << expected_dex_checksum
+ << ", found " << actual_dex_checksum;
return NULL;
}
RegisterOatFileLocked(*oat_file.release());
@@ -722,6 +740,58 @@
return FindOrCreateOatFileForDexLocationLocked(dex_location, oat_location);
}
+class ScopedFlock {
+ public:
+ ScopedFlock() {}
+
+ bool Init(const std::string& filename) {
+ while (true) {
+ file_.reset(OS::OpenFileWithFlags(filename.c_str(), O_CREAT | O_RDWR));
+ if (file_.get() == NULL) {
+ LOG(ERROR) << "Failed to open file: " << filename;
+ return false;
+ }
+ int flock_result = TEMP_FAILURE_RETRY(flock(file_->Fd(), LOCK_EX));
+ if (flock_result != 0) {
+ PLOG(ERROR) << "Failed to lock file: " << filename;
+ return false;
+ }
+ struct stat fstat_stat;
+ int fstat_result = TEMP_FAILURE_RETRY(fstat(file_->Fd(), &fstat_stat));
+ if (fstat_result != 0) {
+ PLOG(ERROR) << "Failed to fstat: " << filename;
+ return false;
+ }
+ struct stat stat_stat;
+ int stat_result = TEMP_FAILURE_RETRY(stat(filename.c_str(), &stat_stat));
+ if (stat_result != 0) {
+ PLOG(WARNING) << "Failed to stat, will retry: " << filename;
+ // ENOENT can happen if someone racing with us unlinks the file we created so just retry.
+ continue;
+ }
+ if (fstat_stat.st_dev != stat_stat.st_dev || fstat_stat.st_ino != stat_stat.st_ino) {
+ LOG(WARNING) << "File changed while locking, will retry: " << filename;
+ continue;
+ }
+ return true;
+ }
+ }
+
+ File& GetFile() {
+ return *file_;
+ }
+
+ ~ScopedFlock() {
+ int flock_result = TEMP_FAILURE_RETRY(flock(file_->Fd(), LOCK_UN));
+ CHECK_EQ(0, flock_result);
+ }
+
+ private:
+ UniquePtr<File> file_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedFlock);
+};
+
const DexFile* ClassLinker::FindOrCreateOatFileForDexLocationLocked(const std::string& dex_location,
const std::string& oat_location) {
uint32_t dex_location_checksum;
@@ -730,6 +800,17 @@
return NULL;
}
+ // We play a locking game here so that if two different processes
+ // race to generate (or worse, one tries to open a partial generated
+ // file) we will be okay. This is actually common with apps that use
+ // DexClassLoader to work around the dex method reference limit and
+ // that have a background service running in a separate process.
+ ScopedFlock scoped_flock;
+ if (!scoped_flock.Init(oat_location)) {
+ LOG(ERROR) << "Failed to open locked oat file: " << oat_location;
+ return NULL;
+ }
+
// Check if we already have an up-to-date output file
const DexFile* dex_file = FindDexFileInOatLocation(dex_location,
dex_location_checksum,
@@ -739,12 +820,8 @@
}
// Generate the output oat file for the dex file
- UniquePtr<File> file(OS::OpenFile(oat_location.c_str(), true));
- if (file.get() == NULL) {
- LOG(ERROR) << "Failed to create oat file: " << oat_location;
- return NULL;
- }
- if (!GenerateOatFile(dex_location, file->Fd(), oat_location)) {
+ VLOG(class_linker) << "Generating oat file " << oat_location << " for " << dex_location;
+ if (!GenerateOatFile(dex_location, scoped_flock.GetFile().Fd(), oat_location)) {
LOG(ERROR) << "Failed to generate oat file: " << oat_location;
return NULL;
}
diff --git a/runtime/dex_file_test.cc b/runtime/dex_file_test.cc
index e7899ec..6449493 100644
--- a/runtime/dex_file_test.cc
+++ b/runtime/dex_file_test.cc
@@ -64,7 +64,7 @@
CHECK(dex_bytes.get() != NULL);
// write to provided file
- UniquePtr<File> file(OS::OpenFile(location.c_str(), true));
+ UniquePtr<File> file(OS::CreateEmptyFile(location.c_str()));
CHECK(file.get() != NULL);
if (!file->WriteFully(dex_bytes.get(), length)) {
PLOG(FATAL) << "Failed to write base64 as dex file";
diff --git a/runtime/entrypoints/entrypoint_utils.cc b/runtime/entrypoints/entrypoint_utils.cc
index 6b8c41e..bf0fffa 100644
--- a/runtime/entrypoints/entrypoint_utils.cc
+++ b/runtime/entrypoints/entrypoint_utils.cc
@@ -269,7 +269,10 @@
}
void ThrowStackOverflowError(Thread* self) {
- CHECK(!self->IsHandlingStackOverflow()) << "Recursive stack overflow.";
+ if (self->IsHandlingStackOverflow()) {
+ LOG(ERROR) << "Recursive stack overflow.";
+ // We don't fail here because SetStackEndForStackOverflow will print better diagnostics.
+ }
if (Runtime::Current()->GetInstrumentation()->AreExitStubsInstalled()) {
// Remove extra entry pushed onto second stack during method tracing.
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index 22562df..f959cff 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -160,7 +160,7 @@
LOG(INFO) << "ImageSpace::Init entering image_file_name=" << image_file_name;
}
- UniquePtr<File> file(OS::OpenFile(image_file_name.c_str(), false));
+ UniquePtr<File> file(OS::OpenFileForReading(image_file_name.c_str()));
if (file.get() == NULL) {
LOG(ERROR) << "Failed to open " << image_file_name;
return NULL;
diff --git a/runtime/image_test.cc b/runtime/image_test.cc
index 334f7ab..dcafc19 100644
--- a/runtime/image_test.cc
+++ b/runtime/image_test.cc
@@ -65,7 +65,7 @@
}
}
// Workound bug that mcld::Linker::emit closes tmp_elf by reopening as tmp_oat.
- UniquePtr<File> tmp_oat(OS::OpenFile(tmp_elf.GetFilename().c_str(), true, false));
+ UniquePtr<File> tmp_oat(OS::OpenFileReadWrite(tmp_elf.GetFilename().c_str()));
ASSERT_TRUE(tmp_oat.get() != NULL);
ScratchFile tmp_image;
@@ -80,7 +80,7 @@
}
{
- UniquePtr<File> file(OS::OpenFile(tmp_image.GetFilename().c_str(), false));
+ UniquePtr<File> file(OS::OpenFileForReading(tmp_image.GetFilename().c_str()));
ASSERT_TRUE(file.get() != NULL);
ImageHeader image_header;
file->ReadFully(&image_header, sizeof(image_header));
diff --git a/runtime/native/dalvik_system_DexFile.cc b/runtime/native/dalvik_system_DexFile.cc
index dc3573d..061dfb8 100644
--- a/runtime/native/dalvik_system_DexFile.cc
+++ b/runtime/native/dalvik_system_DexFile.cc
@@ -84,7 +84,7 @@
void operator=(const NullableScopedUtfChars&);
};
-static jint DexFile_openDexFile(JNIEnv* env, jclass, jstring javaSourceName, jstring javaOutputName, jint) {
+static jint DexFile_openDexFileNative(JNIEnv* env, jclass, jstring javaSourceName, jstring javaOutputName, jint) {
ScopedUtfChars sourceName(env, javaSourceName);
if (sourceName.c_str() == NULL) {
return 0;
@@ -141,21 +141,25 @@
ScopedObjectAccess soa(env);
const DexFile* dex_file = toDexFile(cookie);
if (dex_file == NULL) {
+ VLOG(class_linker) << "Failed to find dex_file";
return NULL;
}
ScopedUtfChars class_name(env, javaName);
if (class_name.c_str() == NULL) {
+ VLOG(class_linker) << "Failed to find class_name";
return NULL;
}
const std::string descriptor(DotToDescriptor(class_name.c_str()));
const DexFile::ClassDef* dex_class_def = dex_file->FindClassDef(descriptor);
if (dex_class_def == NULL) {
+ VLOG(class_linker) << "Failed to find dex_class_def";
return NULL;
}
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
class_linker->RegisterDexFile(*dex_file);
mirror::ClassLoader* class_loader = soa.Decode<mirror::ClassLoader*>(javaLoader);
mirror::Class* result = class_linker->DefineClass(descriptor, class_loader, *dex_file, *dex_class_def);
+ VLOG(class_linker) << "DexFile_defineClassNative returning " << result;
return soa.AddLocalReference<jclass>(result);
}
@@ -300,7 +304,7 @@
NATIVE_METHOD(DexFile, defineClassNative, "(Ljava/lang/String;Ljava/lang/ClassLoader;I)Ljava/lang/Class;"),
NATIVE_METHOD(DexFile, getClassNameList, "(I)[Ljava/lang/String;"),
NATIVE_METHOD(DexFile, isDexOptNeeded, "(Ljava/lang/String;)Z"),
- NATIVE_METHOD(DexFile, openDexFile, "(Ljava/lang/String;Ljava/lang/String;I)I"),
+ NATIVE_METHOD(DexFile, openDexFileNative, "(Ljava/lang/String;Ljava/lang/String;I)I"),
};
void register_dalvik_system_DexFile(JNIEnv* env) {
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index 1f34317..afa823d 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -74,7 +74,7 @@
//
// On host, dlopen is expected to fail when cross compiling, so fall back to OpenElfFile.
// This won't work for portable runtime execution because it doesn't process relocations.
- UniquePtr<File> file(OS::OpenFile(filename.c_str(), false, false));
+ UniquePtr<File> file(OS::OpenFileForReading(filename.c_str()));
if (file.get() == NULL) {
return NULL;
}
@@ -125,11 +125,13 @@
bool OatFile::Dlopen(const std::string& elf_filename, byte* requested_base) {
char* absolute_path = realpath(elf_filename.c_str(), NULL);
if (absolute_path == NULL) {
+ VLOG(class_linker) << "Failed to find absolute path for " << elf_filename;
return false;
}
dlopen_handle_ = dlopen(absolute_path, RTLD_NOW);
free(absolute_path);
if (dlopen_handle_ == NULL) {
+ VLOG(class_linker) << "Failed to dlopen " << elf_filename << ": " << dlerror();
return false;
}
begin_ = reinterpret_cast<byte*>(dlsym(dlopen_handle_, "oatdata"));
@@ -319,7 +321,14 @@
Table::const_iterator it = oat_dex_files_.find(dex_file_location);
if (it == oat_dex_files_.end()) {
if (warn_if_not_found) {
- LOG(WARNING) << "Failed to find OatDexFile for DexFile " << dex_file_location;
+ LOG(WARNING) << "Failed to find OatDexFile for DexFile " << dex_file_location
+ << " in OatFile " << GetLocation();
+ if (kIsDebugBuild) {
+ for (Table::const_iterator it = oat_dex_files_.begin(); it != oat_dex_files_.end(); ++it) {
+ LOG(WARNING) << "OatFile " << GetLocation()
+ << " contains OatDexFile " << it->second->GetDexFileLocation();
+ }
+ }
}
return NULL;
}
@@ -360,11 +369,11 @@
uint32_t oat_class_offset = oat_class_offsets_pointer_[class_def_index];
const byte* oat_class_pointer = oat_file_->Begin() + oat_class_offset;
- CHECK_LT(oat_class_pointer, oat_file_->End());
+ CHECK_LT(oat_class_pointer, oat_file_->End()) << oat_file_->GetLocation();
mirror::Class::Status status = *reinterpret_cast<const mirror::Class::Status*>(oat_class_pointer);
const byte* methods_pointer = oat_class_pointer + sizeof(status);
- CHECK_LT(methods_pointer, oat_file_->End());
+ CHECK_LT(methods_pointer, oat_file_->End()) << oat_file_->GetLocation();
return new OatClass(oat_file_,
status,
diff --git a/runtime/os.h b/runtime/os.h
index 6767566..6248d5f 100644
--- a/runtime/os.h
+++ b/runtime/os.h
@@ -29,8 +29,17 @@
class OS {
public:
- // Open a file. The returned pointer must be deleted by the caller.
- static File* OpenFile(const char* name, bool writable, bool create = true);
+ // Open an existing file with read only access.
+ static File* OpenFileForReading(const char* name);
+
+ // Open an existing file with read/write access.
+ static File* OpenFileReadWrite(const char* name);
+
+ // Create an empty file with read/write access.
+ static File* CreateEmptyFile(const char* name);
+
+ // Open a file with the specified open(2) flags.
+ static File* OpenFileWithFlags(const char* name, int flags);
// Check if a file exists.
static bool FileExists(const char* name);
diff --git a/runtime/os_linux.cc b/runtime/os_linux.cc
index d3a1ccb..7ce17e0 100644
--- a/runtime/os_linux.cc
+++ b/runtime/os_linux.cc
@@ -27,17 +27,20 @@
namespace art {
-File* OS::OpenFile(const char* name, bool writable, bool create) {
+File* OS::OpenFileForReading(const char* name) {
+ return OpenFileWithFlags(name, O_RDONLY);
+}
+
+File* OS::OpenFileReadWrite(const char* name) {
+ return OpenFileWithFlags(name, O_RDWR);
+}
+
+File* OS::CreateEmptyFile(const char* name) {
+ return OpenFileWithFlags(name, O_RDWR | O_CREAT | O_TRUNC);
+}
+
+File* OS::OpenFileWithFlags(const char* name, int flags) {
CHECK(name != NULL);
- int flags = 0;
- if (writable) {
- flags |= O_RDWR;
- if (create) {
- flags |= (O_CREAT | O_TRUNC);
- }
- } else {
- flags |= O_RDONLY;
- }
UniquePtr<File> file(new File);
if (!file->Open(name, flags, 0666)) {
return NULL;
diff --git a/runtime/output_stream_test.cc b/runtime/output_stream_test.cc
index c9e0ede..8da2ac9 100644
--- a/runtime/output_stream_test.cc
+++ b/runtime/output_stream_test.cc
@@ -62,7 +62,7 @@
FileOutputStream output_stream(tmp.GetFile());
SetOutputStream(output_stream);
GenerateTestOutput();
- UniquePtr<File> in(OS::OpenFile(tmp.GetFilename().c_str(), false));
+ UniquePtr<File> in(OS::OpenFileForReading(tmp.GetFilename().c_str()));
EXPECT_TRUE(in.get() != NULL);
std::vector<uint8_t> actual(in->GetLength());
bool readSuccess = in->ReadFully(&actual[0], actual.size());
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 7e3afb5..48e595f 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -2218,11 +2218,13 @@
// Set the stack end to that to be used during a stack overflow
void Thread::SetStackEndForStackOverflow() {
- // During stack overflow we allow use of the full stack
+ // During stack overflow we allow use of the full stack.
if (stack_end_ == stack_begin_) {
- DumpStack(std::cerr);
- LOG(FATAL) << "Need to increase kStackOverflowReservedBytes (currently "
- << kStackOverflowReservedBytes << ")";
+ // However, we seem to have already extended to use the full stack.
+ LOG(ERROR) << "Need to increase kStackOverflowReservedBytes (currently "
+ << kStackOverflowReservedBytes << ")?";
+ DumpStack(LOG(ERROR));
+ LOG(FATAL) << "Recursive stack overflow.";
}
stack_end_ = stack_begin_;
diff --git a/runtime/trace.cc b/runtime/trace.cc
index 29765c9..13e2bf6 100644
--- a/runtime/trace.cc
+++ b/runtime/trace.cc
@@ -318,7 +318,7 @@
UniquePtr<File> trace_file;
if (!direct_to_ddms) {
if (trace_fd < 0) {
- trace_file.reset(OS::OpenFile(trace_filename, true));
+ trace_file.reset(OS::CreateEmptyFile(trace_filename));
} else {
trace_file.reset(new File(trace_fd, "tracefile"));
trace_file->DisableAutoClose();
diff --git a/runtime/utils.cc b/runtime/utils.cc
index 87cd21c..6856bb7 100644
--- a/runtime/utils.cc
+++ b/runtime/utils.cc
@@ -1229,6 +1229,7 @@
bool IsValidOatFilename(const std::string& filename) {
return (EndsWith(filename, ".odex") ||
+ EndsWith(filename, ".dex") ||
EndsWith(filename, ".oat") ||
EndsWith(filename, DexFile::kClassesDex));
}
diff --git a/test/Android.mk b/test/Android.mk
index 87e15a8..596c411 100644
--- a/test/Android.mk
+++ b/test/Android.mk
@@ -111,7 +111,7 @@
$(hide) rm /tmp/test-art-target-oat-$(1)
$(HOST_OUT_JAVA_LIBRARIES)/oat-test-dex-$(1).odex: $(HOST_OUT_JAVA_LIBRARIES)/oat-test-dex-$(1).jar $(HOST_CORE_IMG_OUT) | $(DEX2OAT)
- $(DEX2OAT) --runtime-arg -Xms16m --runtime-arg -Xmx16m --boot-image=$(HOST_CORE_IMG_OUT) --dex-file=$$< --oat-file=$$@ --instruction-set=$(HOST_ARCH) --host --host-prefix="" --android-root=$(HOST_OUT)
+ $(DEX2OAT) --runtime-arg -Xms16m --runtime-arg -Xmx16m --boot-image=$(HOST_CORE_IMG_OUT) --dex-file=$(PWD)/$$< --oat-file=$(PWD)/$$@ --instruction-set=$(HOST_ARCH) --host --host-prefix="" --android-root=$(HOST_OUT)
.PHONY: test-art-host-oat-default-$(1)
test-art-host-oat-default-$(1): $(HOST_OUT_JAVA_LIBRARIES)/oat-test-dex-$(1).odex test-art-host-dependencies