Loading cmds/dumpstate/DumpstateInternal.cpp +7 −11 Original line number Original line Diff line number Diff line Loading @@ -20,6 +20,7 @@ #include <errno.h> #include <errno.h> #include <grp.h> #include <grp.h> #include <poll.h> #include <pwd.h> #include <pwd.h> #include <stdint.h> #include <stdint.h> #include <stdio.h> #include <stdio.h> Loading @@ -35,6 +36,7 @@ #include <vector> #include <vector> #include <android-base/file.h> #include <android-base/file.h> #include <android-base/macros.h> #include <log/log.h> #include <log/log.h> uint64_t Nanotime() { uint64_t Nanotime() { Loading Loading @@ -154,22 +156,16 @@ int DumpFileFromFdToFd(const std::string& title, const std::string& path_string, return 0; return 0; } } bool newline = false; bool newline = false; fd_set read_set; timeval tm; while (true) { while (true) { FD_ZERO(&read_set); uint64_t start_time = Nanotime(); FD_SET(fd, &read_set); pollfd fds[] = { { .fd = fd, .events = POLLIN } }; /* Timeout if no data is read for 30 seconds. */ int ret = TEMP_FAILURE_RETRY(poll(fds, arraysize(fds), 30 * 1000)); tm.tv_sec = 30; tm.tv_usec = 0; uint64_t elapsed = Nanotime(); int ret = TEMP_FAILURE_RETRY(select(fd + 1, &read_set, nullptr, nullptr, &tm)); if (ret == -1) { if (ret == -1) { dprintf(out_fd, "*** %s: select failed: %s\n", path, strerror(errno)); dprintf(out_fd, "*** %s: poll failed: %s\n", path, strerror(errno)); newline = true; newline = true; break; break; } else if (ret == 0) { } else if (ret == 0) { elapsed = Nanotime() - elapsed; uint64_t elapsed = Nanotime() - start_time; dprintf(out_fd, "*** %s: Timed out after %.3fs\n", path, (float)elapsed / NANOS_PER_SEC); dprintf(out_fd, "*** %s: Timed out after %.3fs\n", path, (float)elapsed / NANOS_PER_SEC); newline = true; newline = true; break; break; Loading cmds/dumpstate/dumpstate.cpp +22 −40 Original line number Original line Diff line number Diff line Loading @@ -112,19 +112,6 @@ static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_"; static const std::string ANR_DIR = "/data/anr/"; static const std::string ANR_DIR = "/data/anr/"; static const std::string ANR_FILE_PREFIX = "anr_"; static const std::string ANR_FILE_PREFIX = "anr_"; struct DumpData { std::string name; int fd; time_t mtime; }; static bool operator<(const DumpData& d1, const DumpData& d2) { return d1.mtime > d2.mtime; } static std::unique_ptr<std::vector<DumpData>> tombstone_data; static std::unique_ptr<std::vector<DumpData>> anr_data; // TODO: temporary variables and functions used during C++ refactoring // TODO: temporary variables and functions used during C++ refactoring static Dumpstate& ds = Dumpstate::GetInstance(); static Dumpstate& ds = Dumpstate::GetInstance(); static int RunCommand(const std::string& title, const std::vector<std::string>& fullCommand, static int RunCommand(const std::string& title, const std::vector<std::string>& fullCommand, Loading Loading @@ -167,20 +154,20 @@ static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot( * is set, the vector only contains files that were written in the last 30 minutes. * is set, the vector only contains files that were written in the last 30 minutes. * If |limit_by_count| is set, the vector only contains the ten latest files. * If |limit_by_count| is set, the vector only contains the ten latest files. */ */ static std::vector<DumpData>* GetDumpFds(const std::string& dir_path, static std::vector<DumpData> GetDumpFds(const std::string& dir_path, const std::string& file_prefix, const std::string& file_prefix, bool limit_by_mtime, bool limit_by_mtime, bool limit_by_count = true) { bool limit_by_count = true) { const time_t thirty_minutes_ago = ds.now_ - 60 * 30; const time_t thirty_minutes_ago = ds.now_ - 60 * 30; std::unique_ptr<std::vector<DumpData>> dump_data(new std::vector<DumpData>()); std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir); std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir); if (dump_dir == nullptr) { if (dump_dir == nullptr) { MYLOGW("Unable to open directory %s: %s\n", dir_path.c_str(), strerror(errno)); MYLOGW("Unable to open directory %s: %s\n", dir_path.c_str(), strerror(errno)); return dump_data.release(); return std::vector<DumpData>(); } } std::vector<DumpData> dump_data; struct dirent* entry = nullptr; struct dirent* entry = nullptr; while ((entry = readdir(dump_dir.get()))) { while ((entry = readdir(dump_dir.get()))) { if (entry->d_type != DT_REG) { if (entry->d_type != DT_REG) { Loading Loading @@ -211,18 +198,19 @@ static std::vector<DumpData>* GetDumpFds(const std::string& dir_path, continue; continue; } } DumpData data = {.name = abs_path, .fd = fd.release(), .mtime = st.st_mtime}; dump_data.emplace_back(DumpData{abs_path, std::move(fd), st.st_mtime}); dump_data->push_back(data); } } std::sort(dump_data->begin(), dump_data->end()); // Sort in descending modification time so that we only keep the newest // reports if |limit_by_count| is true. std::sort(dump_data.begin(), dump_data.end(), [](const DumpData& d1, const DumpData& d2) { return d1.mtime > d2.mtime; }); if (limit_by_count && dump_data->size() > 10) { if (limit_by_count && dump_data.size() > 10) { dump_data->erase(dump_data->begin() + 10, dump_data->end()); dump_data.erase(dump_data.begin() + 10, dump_data.end()); } } return dump_data.release(); return dump_data; } } static bool AddDumps(const std::vector<DumpData>::const_iterator start, static bool AddDumps(const std::vector<DumpData>::const_iterator start, Loading Loading @@ -257,12 +245,6 @@ static bool AddDumps(const std::vector<DumpData>::const_iterator start, return dumped; return dumped; } } static void CloseDumpFds(const std::vector<DumpData>* dumps) { for (auto it = dumps->begin(); it != dumps->end(); ++it) { close(it->fd); } } // for_each_pid() callback to get mount info about a process. // for_each_pid() callback to get mount info about a process. void do_mountinfo(int pid, const char* name __attribute__((unused))) { void do_mountinfo(int pid, const char* name __attribute__((unused))) { char path[PATH_MAX]; char path[PATH_MAX]; Loading Loading @@ -1007,15 +989,15 @@ static void AddAnrTraceDir(const bool add_to_zip, const std::string& anr_traces_ } } // Add a specific message for the first ANR Dump. // Add a specific message for the first ANR Dump. if (anr_data->size() > 0) { if (ds.anr_data_.size() > 0) { AddDumps(anr_data->begin(), anr_data->begin() + 1, AddDumps(ds.anr_data_.begin(), ds.anr_data_.begin() + 1, "VM TRACES AT LAST ANR", add_to_zip); "VM TRACES AT LAST ANR", add_to_zip); // The "last" ANR will always be included as separate entry in the zip file. In addition, // The "last" ANR will always be included as separate entry in the zip file. In addition, // it will be present in the body of the main entry if |add_to_zip| == false. // it will be present in the body of the main entry if |add_to_zip| == false. // // // Historical ANRs are always included as separate entries in the bugreport zip file. // Historical ANRs are always included as separate entries in the bugreport zip file. AddDumps(anr_data->begin() + ((add_to_zip) ? 1 : 0), anr_data->end(), AddDumps(ds.anr_data_.begin() + ((add_to_zip) ? 1 : 0), ds.anr_data_.end(), "HISTORICAL ANR", true /* add_to_zip */); "HISTORICAL ANR", true /* add_to_zip */); } else { } else { printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str()); printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str()); Loading Loading @@ -1362,7 +1344,7 @@ static void dumpstate() { // NOTE: tombstones are always added as separate entries in the zip archive // NOTE: tombstones are always added as separate entries in the zip archive // and are not interspersed with the main report. // and are not interspersed with the main report. const bool tombstones_dumped = AddDumps(tombstone_data->begin(), tombstone_data->end(), const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(), "TOMBSTONE", true /* add_to_zip */); "TOMBSTONE", true /* add_to_zip */); if (!tombstones_dumped) { if (!tombstones_dumped) { printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str()); printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str()); Loading Loading @@ -2114,8 +2096,8 @@ int run_main(int argc, char* argv[]) { dump_traces_path = dump_traces(); dump_traces_path = dump_traces(); /* Run some operations that require root. */ /* Run some operations that require root. */ tombstone_data.reset(GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping())); ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping()); anr_data.reset(GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping())); ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping()); ds.AddDir(RECOVERY_DIR, true); ds.AddDir(RECOVERY_DIR, true); ds.AddDir(RECOVERY_DATA_DIR, true); ds.AddDir(RECOVERY_DATA_DIR, true); Loading Loading @@ -2288,8 +2270,8 @@ int run_main(int argc, char* argv[]) { close(ds.control_socket_fd_); close(ds.control_socket_fd_); } } CloseDumpFds(tombstone_data.get()); ds.tombstone_data_.clear(); CloseDumpFds(anr_data.get()); ds.anr_data_.clear(); return 0; return 0; } } cmds/dumpstate/dumpstate.h +21 −0 Original line number Original line Diff line number Diff line Loading @@ -26,6 +26,7 @@ #include <vector> #include <vector> #include <android-base/macros.h> #include <android-base/macros.h> #include <android-base/unique_fd.h> #include <android/os/IDumpstateListener.h> #include <android/os/IDumpstateListener.h> #include <utils/StrongPointer.h> #include <utils/StrongPointer.h> #include <ziparchive/zip_writer.h> #include <ziparchive/zip_writer.h> Loading Loading @@ -158,6 +159,20 @@ static std::string VERSION_SPLIT_ANR = "3.0-dev-split-anr"; */ */ static std::string VERSION_DEFAULT = "default"; static std::string VERSION_DEFAULT = "default"; /* * Structure that contains the information of an open dump file. */ struct DumpData { // Path of the file. std::string name; // Open file descriptor for the file. android::base::unique_fd fd; // Modification time of the file. time_t mtime; }; /* /* * Main class driving a bugreport generation. * Main class driving a bugreport generation. * * Loading Loading @@ -350,6 +365,12 @@ class Dumpstate { std::string notification_title; std::string notification_title; std::string notification_description; std::string notification_description; // List of open tombstone dump files. std::vector<DumpData> tombstone_data_; // List of open ANR dump files. std::vector<DumpData> anr_data_; private: private: // Used by GetInstance() only. // Used by GetInstance() only. Dumpstate(const std::string& version = VERSION_CURRENT); Dumpstate(const std::string& version = VERSION_CURRENT); Loading vulkan/Android.bp +6 −0 Original line number Original line Diff line number Diff line Loading @@ -45,6 +45,12 @@ cc_library_headers { sdk_version: "24", sdk_version: "24", } } llndk_library { name: "libvulkan", symbol_file: "libvulkan/libvulkan.map.txt", export_include_dirs: ["include"], } subdirs = [ subdirs = [ "nulldrv", "nulldrv", "libvulkan", "libvulkan", Loading Loading
cmds/dumpstate/DumpstateInternal.cpp +7 −11 Original line number Original line Diff line number Diff line Loading @@ -20,6 +20,7 @@ #include <errno.h> #include <errno.h> #include <grp.h> #include <grp.h> #include <poll.h> #include <pwd.h> #include <pwd.h> #include <stdint.h> #include <stdint.h> #include <stdio.h> #include <stdio.h> Loading @@ -35,6 +36,7 @@ #include <vector> #include <vector> #include <android-base/file.h> #include <android-base/file.h> #include <android-base/macros.h> #include <log/log.h> #include <log/log.h> uint64_t Nanotime() { uint64_t Nanotime() { Loading Loading @@ -154,22 +156,16 @@ int DumpFileFromFdToFd(const std::string& title, const std::string& path_string, return 0; return 0; } } bool newline = false; bool newline = false; fd_set read_set; timeval tm; while (true) { while (true) { FD_ZERO(&read_set); uint64_t start_time = Nanotime(); FD_SET(fd, &read_set); pollfd fds[] = { { .fd = fd, .events = POLLIN } }; /* Timeout if no data is read for 30 seconds. */ int ret = TEMP_FAILURE_RETRY(poll(fds, arraysize(fds), 30 * 1000)); tm.tv_sec = 30; tm.tv_usec = 0; uint64_t elapsed = Nanotime(); int ret = TEMP_FAILURE_RETRY(select(fd + 1, &read_set, nullptr, nullptr, &tm)); if (ret == -1) { if (ret == -1) { dprintf(out_fd, "*** %s: select failed: %s\n", path, strerror(errno)); dprintf(out_fd, "*** %s: poll failed: %s\n", path, strerror(errno)); newline = true; newline = true; break; break; } else if (ret == 0) { } else if (ret == 0) { elapsed = Nanotime() - elapsed; uint64_t elapsed = Nanotime() - start_time; dprintf(out_fd, "*** %s: Timed out after %.3fs\n", path, (float)elapsed / NANOS_PER_SEC); dprintf(out_fd, "*** %s: Timed out after %.3fs\n", path, (float)elapsed / NANOS_PER_SEC); newline = true; newline = true; break; break; Loading
cmds/dumpstate/dumpstate.cpp +22 −40 Original line number Original line Diff line number Diff line Loading @@ -112,19 +112,6 @@ static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_"; static const std::string ANR_DIR = "/data/anr/"; static const std::string ANR_DIR = "/data/anr/"; static const std::string ANR_FILE_PREFIX = "anr_"; static const std::string ANR_FILE_PREFIX = "anr_"; struct DumpData { std::string name; int fd; time_t mtime; }; static bool operator<(const DumpData& d1, const DumpData& d2) { return d1.mtime > d2.mtime; } static std::unique_ptr<std::vector<DumpData>> tombstone_data; static std::unique_ptr<std::vector<DumpData>> anr_data; // TODO: temporary variables and functions used during C++ refactoring // TODO: temporary variables and functions used during C++ refactoring static Dumpstate& ds = Dumpstate::GetInstance(); static Dumpstate& ds = Dumpstate::GetInstance(); static int RunCommand(const std::string& title, const std::vector<std::string>& fullCommand, static int RunCommand(const std::string& title, const std::vector<std::string>& fullCommand, Loading Loading @@ -167,20 +154,20 @@ static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot( * is set, the vector only contains files that were written in the last 30 minutes. * is set, the vector only contains files that were written in the last 30 minutes. * If |limit_by_count| is set, the vector only contains the ten latest files. * If |limit_by_count| is set, the vector only contains the ten latest files. */ */ static std::vector<DumpData>* GetDumpFds(const std::string& dir_path, static std::vector<DumpData> GetDumpFds(const std::string& dir_path, const std::string& file_prefix, const std::string& file_prefix, bool limit_by_mtime, bool limit_by_mtime, bool limit_by_count = true) { bool limit_by_count = true) { const time_t thirty_minutes_ago = ds.now_ - 60 * 30; const time_t thirty_minutes_ago = ds.now_ - 60 * 30; std::unique_ptr<std::vector<DumpData>> dump_data(new std::vector<DumpData>()); std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir); std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir); if (dump_dir == nullptr) { if (dump_dir == nullptr) { MYLOGW("Unable to open directory %s: %s\n", dir_path.c_str(), strerror(errno)); MYLOGW("Unable to open directory %s: %s\n", dir_path.c_str(), strerror(errno)); return dump_data.release(); return std::vector<DumpData>(); } } std::vector<DumpData> dump_data; struct dirent* entry = nullptr; struct dirent* entry = nullptr; while ((entry = readdir(dump_dir.get()))) { while ((entry = readdir(dump_dir.get()))) { if (entry->d_type != DT_REG) { if (entry->d_type != DT_REG) { Loading Loading @@ -211,18 +198,19 @@ static std::vector<DumpData>* GetDumpFds(const std::string& dir_path, continue; continue; } } DumpData data = {.name = abs_path, .fd = fd.release(), .mtime = st.st_mtime}; dump_data.emplace_back(DumpData{abs_path, std::move(fd), st.st_mtime}); dump_data->push_back(data); } } std::sort(dump_data->begin(), dump_data->end()); // Sort in descending modification time so that we only keep the newest // reports if |limit_by_count| is true. std::sort(dump_data.begin(), dump_data.end(), [](const DumpData& d1, const DumpData& d2) { return d1.mtime > d2.mtime; }); if (limit_by_count && dump_data->size() > 10) { if (limit_by_count && dump_data.size() > 10) { dump_data->erase(dump_data->begin() + 10, dump_data->end()); dump_data.erase(dump_data.begin() + 10, dump_data.end()); } } return dump_data.release(); return dump_data; } } static bool AddDumps(const std::vector<DumpData>::const_iterator start, static bool AddDumps(const std::vector<DumpData>::const_iterator start, Loading Loading @@ -257,12 +245,6 @@ static bool AddDumps(const std::vector<DumpData>::const_iterator start, return dumped; return dumped; } } static void CloseDumpFds(const std::vector<DumpData>* dumps) { for (auto it = dumps->begin(); it != dumps->end(); ++it) { close(it->fd); } } // for_each_pid() callback to get mount info about a process. // for_each_pid() callback to get mount info about a process. void do_mountinfo(int pid, const char* name __attribute__((unused))) { void do_mountinfo(int pid, const char* name __attribute__((unused))) { char path[PATH_MAX]; char path[PATH_MAX]; Loading Loading @@ -1007,15 +989,15 @@ static void AddAnrTraceDir(const bool add_to_zip, const std::string& anr_traces_ } } // Add a specific message for the first ANR Dump. // Add a specific message for the first ANR Dump. if (anr_data->size() > 0) { if (ds.anr_data_.size() > 0) { AddDumps(anr_data->begin(), anr_data->begin() + 1, AddDumps(ds.anr_data_.begin(), ds.anr_data_.begin() + 1, "VM TRACES AT LAST ANR", add_to_zip); "VM TRACES AT LAST ANR", add_to_zip); // The "last" ANR will always be included as separate entry in the zip file. In addition, // The "last" ANR will always be included as separate entry in the zip file. In addition, // it will be present in the body of the main entry if |add_to_zip| == false. // it will be present in the body of the main entry if |add_to_zip| == false. // // // Historical ANRs are always included as separate entries in the bugreport zip file. // Historical ANRs are always included as separate entries in the bugreport zip file. AddDumps(anr_data->begin() + ((add_to_zip) ? 1 : 0), anr_data->end(), AddDumps(ds.anr_data_.begin() + ((add_to_zip) ? 1 : 0), ds.anr_data_.end(), "HISTORICAL ANR", true /* add_to_zip */); "HISTORICAL ANR", true /* add_to_zip */); } else { } else { printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str()); printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str()); Loading Loading @@ -1362,7 +1344,7 @@ static void dumpstate() { // NOTE: tombstones are always added as separate entries in the zip archive // NOTE: tombstones are always added as separate entries in the zip archive // and are not interspersed with the main report. // and are not interspersed with the main report. const bool tombstones_dumped = AddDumps(tombstone_data->begin(), tombstone_data->end(), const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(), "TOMBSTONE", true /* add_to_zip */); "TOMBSTONE", true /* add_to_zip */); if (!tombstones_dumped) { if (!tombstones_dumped) { printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str()); printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str()); Loading Loading @@ -2114,8 +2096,8 @@ int run_main(int argc, char* argv[]) { dump_traces_path = dump_traces(); dump_traces_path = dump_traces(); /* Run some operations that require root. */ /* Run some operations that require root. */ tombstone_data.reset(GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping())); ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping()); anr_data.reset(GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping())); ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping()); ds.AddDir(RECOVERY_DIR, true); ds.AddDir(RECOVERY_DIR, true); ds.AddDir(RECOVERY_DATA_DIR, true); ds.AddDir(RECOVERY_DATA_DIR, true); Loading Loading @@ -2288,8 +2270,8 @@ int run_main(int argc, char* argv[]) { close(ds.control_socket_fd_); close(ds.control_socket_fd_); } } CloseDumpFds(tombstone_data.get()); ds.tombstone_data_.clear(); CloseDumpFds(anr_data.get()); ds.anr_data_.clear(); return 0; return 0; } }
cmds/dumpstate/dumpstate.h +21 −0 Original line number Original line Diff line number Diff line Loading @@ -26,6 +26,7 @@ #include <vector> #include <vector> #include <android-base/macros.h> #include <android-base/macros.h> #include <android-base/unique_fd.h> #include <android/os/IDumpstateListener.h> #include <android/os/IDumpstateListener.h> #include <utils/StrongPointer.h> #include <utils/StrongPointer.h> #include <ziparchive/zip_writer.h> #include <ziparchive/zip_writer.h> Loading Loading @@ -158,6 +159,20 @@ static std::string VERSION_SPLIT_ANR = "3.0-dev-split-anr"; */ */ static std::string VERSION_DEFAULT = "default"; static std::string VERSION_DEFAULT = "default"; /* * Structure that contains the information of an open dump file. */ struct DumpData { // Path of the file. std::string name; // Open file descriptor for the file. android::base::unique_fd fd; // Modification time of the file. time_t mtime; }; /* /* * Main class driving a bugreport generation. * Main class driving a bugreport generation. * * Loading Loading @@ -350,6 +365,12 @@ class Dumpstate { std::string notification_title; std::string notification_title; std::string notification_description; std::string notification_description; // List of open tombstone dump files. std::vector<DumpData> tombstone_data_; // List of open ANR dump files. std::vector<DumpData> anr_data_; private: private: // Used by GetInstance() only. // Used by GetInstance() only. Dumpstate(const std::string& version = VERSION_CURRENT); Dumpstate(const std::string& version = VERSION_CURRENT); Loading
vulkan/Android.bp +6 −0 Original line number Original line Diff line number Diff line Loading @@ -45,6 +45,12 @@ cc_library_headers { sdk_version: "24", sdk_version: "24", } } llndk_library { name: "libvulkan", symbol_file: "libvulkan/libvulkan.map.txt", export_include_dirs: ["include"], } subdirs = [ subdirs = [ "nulldrv", "nulldrv", "libvulkan", "libvulkan", Loading