}
static FILE* CreateTempFp() {
- std::unique_ptr<TemporaryFile> tmpfile = CreateTempFileUsedInRecording();
+ std::unique_ptr<TemporaryFile> tmpfile = ScopedTempFiles::CreateTempFile();
FILE* fp = fdopen(tmpfile->release(), "web+");
if (fp == nullptr) {
PLOG(ERROR) << "fdopen";
#else
std::string tmpdir = "/tmp";
#endif
- SetTempDirectoryUsedInRecording(tmpdir);
+ scoped_temp_files_.reset(new ScopedTempFiles(tmpdir));
}
+
+ private:
+ std::unique_ptr<ScopedTempFiles> scoped_temp_files_;
};
TEST_F(CallChainJoinerTest, smoke) {
if (!ParseOptions(args)) {
return false;
}
+ ScopedTempFiles scoped_temp_files(android::base::Dirname(output_filename_));
// 2. Read input perf.data, and generate new perf.data.
if (!UnwindRecordFile()) {
return false;
}
}
- SetTempDirectoryUsedInRecording(android::base::Dirname(output_filename_));
return true;
}
return false;
}
writer_.reset();
- std::unique_ptr<TemporaryFile> tmpfile = CreateTempFileUsedInRecording();
- if (!Workload::RunCmd({"mv", output_filename_, tmpfile->path})) {
+ std::unique_ptr<TemporaryFile> tmp_file = ScopedTempFiles::CreateTempFile();
+ if (!Workload::RunCmd({"mv", output_filename_, tmp_file->path})) {
return false;
}
// 3. Read records from the temporary file, and write records with joined call chains back
// to record_filename_.
- std::unique_ptr<RecordFileReader> reader = RecordFileReader::CreateInstance(tmpfile->path);
+ std::unique_ptr<RecordFileReader> reader = RecordFileReader::CreateInstance(tmp_file->path);
if (!reader) {
return false;
}
if (!ParseOptions(args, &workload_args)) {
return false;
}
+ ScopedTempFiles scoped_temp_files(android::base::Dirname(record_filename_));
if (!app_package_name_.empty() && !in_app_context_) {
// Some users want to profile non debuggable apps on rooted devices. If we use run-as,
// it will be impossible when using --app. So don't switch to app's context when we are
for (; i < args.size(); ++i) {
non_option_args->push_back(args[i]);
}
-
- SetTempDirectoryUsedInRecording(android::base::Dirname(record_filename_));
return true;
}
return false;
}
record_file_writer_.reset();
- std::unique_ptr<TemporaryFile> tmpfile = CreateTempFileUsedInRecording();
- if (!Workload::RunCmd({"mv", record_filename_, tmpfile->path})) {
+ std::unique_ptr<TemporaryFile> tmp_file = ScopedTempFiles::CreateTempFile();
+ if (!Workload::RunCmd({"mv", record_filename_, tmp_file->path})) {
return false;
}
- std::unique_ptr<RecordFileReader> reader = RecordFileReader::CreateInstance(tmpfile->path);
+ std::unique_ptr<RecordFileReader> reader = RecordFileReader::CreateInstance(tmp_file->path);
if (!reader) {
return false;
}
return false;
}
record_file_writer_.reset();
- std::unique_ptr<TemporaryFile> tmpfile = CreateTempFileUsedInRecording();
- if (!Workload::RunCmd({"mv", record_filename_, tmpfile->path})) {
+ std::unique_ptr<TemporaryFile> tmp_file = ScopedTempFiles::CreateTempFile();
+ if (!Workload::RunCmd({"mv", record_filename_, tmp_file->path})) {
return false;
}
// 3. Read records from the temporary file, and write record with joined call chains back
// to record_filename_.
- std::unique_ptr<RecordFileReader> reader = RecordFileReader::CreateInstance(tmpfile->path);
+ std::unique_ptr<RecordFileReader> reader = RecordFileReader::CreateInstance(tmp_file->path);
record_file_writer_ = CreateRecordFile(record_filename_);
if (!reader || !record_file_writer_) {
return false;
std::unordered_map<std::string, BuildId> Dso::build_id_map_;
size_t Dso::dso_count_;
uint32_t Dso::g_dump_id_;
-std::unique_ptr<TemporaryFile> Dso::vdso_64bit_;
-std::unique_ptr<TemporaryFile> Dso::vdso_32bit_;
+std::string Dso::vdso_64bit_;
+std::string Dso::vdso_32bit_;
void Dso::SetDemangle(bool demangle) { demangle_ = demangle; }
build_id_map_ = std::move(map);
}
-void Dso::SetVdsoFile(std::unique_ptr<TemporaryFile> vdso_file, bool is_64bit) {
+void Dso::SetVdsoFile(const std::string& vdso_file, bool is_64bit) {
if (is_64bit) {
- vdso_64bit_ = std::move(vdso_file);
+ vdso_64bit_ = vdso_file;
} else {
- vdso_32bit_ = std::move(vdso_file);
+ vdso_32bit_ = vdso_file;
}
}
debug_file_path_ = path_in_symfs;
}
} else if (path == "[vdso]") {
- if (force_64bit && vdso_64bit_ != nullptr) {
- debug_file_path_ = vdso_64bit_->path;
- } else if (!force_64bit && vdso_32bit_ != nullptr) {
- debug_file_path_ = vdso_32bit_->path;
+ if (force_64bit && !vdso_64bit_.empty()) {
+ debug_file_path_ = vdso_64bit_;
+ } else if (!force_64bit && !vdso_32bit_.empty()) {
+ debug_file_path_ = vdso_32bit_;
}
}
size_t pos = path.find_last_of("/\\");
read_kernel_symbols_from_proc_ = false;
build_id_map_.clear();
g_dump_id_ = 0;
- vdso_64bit_ = nullptr;
- vdso_32bit_ = nullptr;
}
}
static void SetBuildIds(
const std::vector<std::pair<std::string, BuildId>>& build_ids);
static BuildId FindExpectedBuildIdForPath(const std::string& path);
- static void SetVdsoFile(std::unique_ptr<TemporaryFile> vdso_file, bool is_64bit);
+ static void SetVdsoFile(const std::string& vdso_file, bool is_64bit);
static std::unique_ptr<Dso> CreateDso(DsoType dso_type, const std::string& dso_path,
bool force_64bit = false);
static std::unordered_map<std::string, BuildId> build_id_map_;
static size_t dso_count_;
static uint32_t g_dump_id_;
- static std::unique_ptr<TemporaryFile> vdso_64bit_;
- static std::unique_ptr<TemporaryFile> vdso_32bit_;
+ static std::string vdso_64bit_;
+ static std::string vdso_32bit_;
Dso(DsoType type, const std::string& path, bool force_64bit);
void Load();
std::string s(vdso_map->len, '\0');
memcpy(&s[0], reinterpret_cast<void*>(static_cast<uintptr_t>(vdso_map->start_addr)),
vdso_map->len);
- std::unique_ptr<TemporaryFile> tmpfile = CreateTempFileUsedInRecording();
- if (!android::base::WriteStringToFile(s, tmpfile->path)) {
+ std::unique_ptr<TemporaryFile> tmpfile = ScopedTempFiles::CreateTempFile();
+ if (!android::base::WriteStringToFd(s, tmpfile->release())) {
return;
}
- Dso::SetVdsoFile(std::move(tmpfile), sizeof(size_t) == sizeof(uint64_t));
+ Dso::SetVdsoFile(tmpfile->path, sizeof(size_t) == sizeof(uint64_t));
}
static bool HasOpenedAppApkFile(int pid) {
}
}
-static std::string temp_dir_used_in_recording;
-void SetTempDirectoryUsedInRecording(const std::string& tmp_dir) {
- temp_dir_used_in_recording = tmp_dir;
+std::string ScopedTempFiles::tmp_dir_;
+std::vector<std::string> ScopedTempFiles::files_to_delete_;
+
+ScopedTempFiles::ScopedTempFiles(const std::string& tmp_dir) {
+ CHECK(tmp_dir_.empty()); // No other ScopedTempFiles.
+ tmp_dir_ = tmp_dir;
}
-std::unique_ptr<TemporaryFile> CreateTempFileUsedInRecording() {
- CHECK(!temp_dir_used_in_recording.empty());
- return std::unique_ptr<TemporaryFile>(new TemporaryFile(temp_dir_used_in_recording));
+ScopedTempFiles::~ScopedTempFiles() {
+ tmp_dir_.clear();
+ for (auto& file : files_to_delete_) {
+ unlink(file.c_str());
+ }
+ files_to_delete_.clear();
+}
+
+std::unique_ptr<TemporaryFile> ScopedTempFiles::CreateTempFile(bool delete_in_destructor) {
+ CHECK(!tmp_dir_.empty());
+ std::unique_ptr<TemporaryFile> tmp_file(new TemporaryFile(tmp_dir_));
+ CHECK_NE(tmp_file->fd, -1);
+ if (delete_in_destructor) {
+ files_to_delete_.push_back(tmp_file->path);
+ }
+ return tmp_file;
}
bool SignalIsIgnored(int signo) {
const std::string& GetDefaultAppPackageName();
void AllowMoreOpenedFiles();
-void SetTempDirectoryUsedInRecording(const std::string& tmp_dir);
-std::unique_ptr<TemporaryFile> CreateTempFileUsedInRecording();
+class ScopedTempFiles {
+ public:
+ ScopedTempFiles(const std::string& tmp_dir);
+ ~ScopedTempFiles();
+ // If delete_in_destructor = true, the temp file will be deleted in the destructor of
+ // ScopedTempFile. Otherwise, it should be deleted by the caller.
+ static std::unique_ptr<TemporaryFile> CreateTempFile(bool delete_in_destructor = true);
+
+ private:
+ static std::string tmp_dir_;
+ static std::vector<std::string> files_to_delete_;
+};
bool SignalIsIgnored(int signo);
return;
}
TemporaryDir tmpdir;
- SetTempDirectoryUsedInRecording(tmpdir.path);
+ ScopedTempFiles scoped_temp_files(tmpdir.path);
PrepareVdsoFile();
std::unique_ptr<Dso> dso = Dso::CreateDso(DSO_ELF_FILE, "[vdso]",
sizeof(size_t) == sizeof(uint64_t));