Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d3badbae authored by Narayan Kamath's avatar Narayan Kamath
Browse files

dumpstate: always include last ANR as a separate entry.

For consistency, as well as to make tooling easier.

Most of this change is an extended yak-shave to try and close DumpData
FDs in a consistent manner. Several layers of abstraction were assuming
that it was their job to close input FDs, leading to double closes in some
cases. These double closes are benign prior to this change to dump a
given DumpData twice, given that dumpstate is single threaded.

Bug: 68188758
Test: adb bugreport

(cherry picked from commit 6b9516ce)

Merged-In: I6302f4cb553139c0c26defb4859c4eca5b18ec93
Change-Id: I54ba5e11135b6aefa97d95b287e00325b5867c8a
parent 534830dc
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -153,7 +153,6 @@ int DumpFileFromFdToFd(const std::string& title, const std::string& path_string,
            }
        }
    }
    close(fd);

    if (!newline) dprintf(out_fd, "\n");
    if (!title.empty()) dprintf(out_fd, "\n");
+4 −3
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
#include <cutils/log.h>

#include "DumpstateInternal.h"
@@ -182,8 +183,8 @@ bool PropertiesHelper::IsDryRun() {
}

int DumpFileToFd(int out_fd, const std::string& title, const std::string& path) {
    int fd = TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC));
    if (fd < 0) {
    android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
    if (fd.get() < 0) {
        int err = errno;
        if (title.empty()) {
            dprintf(out_fd, "*** Error dumping %s: %s\n", path.c_str(), strerror(err));
@@ -194,7 +195,7 @@ int DumpFileToFd(int out_fd, const std::string& title, const std::string& path)
        fsync(out_fd);
        return -1;
    }
    return DumpFileFromFdToFd(title, path, fd, out_fd, PropertiesHelper::IsDryRun());
    return DumpFileFromFdToFd(title, path, fd.get(), out_fd, PropertiesHelper::IsDryRun());
}

int RunCommandToFd(int fd, const std::string& title, const std::vector<std::string>& full_command,
+32 −13
Original line number Diff line number Diff line
@@ -202,20 +202,36 @@ static bool AddDumps(const std::vector<DumpData>::const_iterator start,
        const std::string& name = it->name;
        const int fd = it->fd;
        dumped = true;

        // Seek to the beginning of the file before dumping any data. A given
        // DumpData entry might be dumped multiple times in the report.
        //
        // For example, the most recent ANR entry is dumped to the body of the
        // main entry and it also shows up as a separate entry in the bugreport
        // ZIP file.
        if (lseek(fd, 0, SEEK_SET) != static_cast<off_t>(0)) {
            MYLOGE("Unable to add %s to zip file, lseek failed: %s\n", name.c_str(),
                   strerror(errno));
        }

        if (ds.IsZipping() && add_to_zip) {
            if (!ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd)) {
                MYLOGE("Unable to add %s %s to zip file\n", name.c_str(), type_name);
                MYLOGE("Unable to add %s to zip file, addZipEntryFromFd failed\n", name.c_str());
            }
        } else {
            dump_file_from_fd(type_name, name.c_str(), fd);
        }

        close(fd);
    }

    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.
void do_mountinfo(int pid, const char* name __attribute__((unused))) {
    char path[PATH_MAX];
@@ -882,9 +898,9 @@ static void AddGlobalAnrTraceFile(const bool add_to_zip, const std::string& anr_
    MYLOGD("AddGlobalAnrTraceFile(): dump_traces_dir=%s, anr_traces_dir=%s, already_dumped=%d\n",
           dump_traces_dir.c_str(), anr_traces_dir.c_str(), already_dumped);

    int fd = TEMP_FAILURE_RETRY(
        open(anr_traces_file.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
    if (fd < 0) {
    android::base::unique_fd fd(TEMP_FAILURE_RETRY(
        open(anr_traces_file.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
    if (fd.get() < 0) {
        printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anr_traces_file.c_str(), strerror(errno));
    } else {
        if (add_to_zip) {
@@ -896,7 +912,7 @@ static void AddGlobalAnrTraceFile(const bool add_to_zip, const std::string& anr_
        } else {
            MYLOGD("Dumping last ANR traces (%s) to the main bugreport entry\n",
                   anr_traces_file.c_str());
            dump_file_from_fd("VM TRACES AT LAST ANR", anr_traces_file.c_str(), fd);
            dump_file_from_fd("VM TRACES AT LAST ANR", anr_traces_file.c_str(), fd.get());
        }
    }
}
@@ -929,12 +945,12 @@ static void AddAnrTraceDir(const bool add_to_zip, const std::string& anr_traces_
        AddDumps(anr_data->begin(), anr_data->begin() + 1,
                 "VM TRACES AT LAST ANR", add_to_zip);

        if (anr_data->size() > 1) {
            // NOTE: Historical ANRs are always added as separate entries in the
            // bugreport zip file.
            AddDumps(anr_data->begin() + 1, anr_data->end(),
        // 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.
        //
        // 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(),
                 "HISTORICAL ANR", true /* add_to_zip */);
        }
    } else {
        printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
    }
@@ -1994,5 +2010,8 @@ int main(int argc, char *argv[]) {
        close(ds.control_socket_fd_);
    }

    CloseDumpFds(tombstone_data.get());
    CloseDumpFds(anr_data.get());

    return 0;
}
+5 −7
Original line number Diff line number Diff line
@@ -628,7 +628,7 @@ int dump_files(const std::string& title, const char* dir, bool (*skip)(const cha
    struct dirent *d;
    char *newpath = NULL;
    const char *slash = "/";
    int fd, retval = 0;
    int retval = 0;

    if (!title.empty()) {
        printf("------ %s (%s) ------\n", title.c_str(), dir);
@@ -670,13 +670,13 @@ int dump_files(const std::string& title, const char* dir, bool (*skip)(const cha
            }
            continue;
        }
        fd = TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC));
        if (fd < 0) {
            retval = fd;
        android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
        if (fd.get() < 0) {
            retval = -1;
            printf("*** %s: %s\n", newpath, strerror(errno));
            continue;
        }
        (*dump_from_fd)(NULL, newpath, fd);
        (*dump_from_fd)(NULL, newpath, fd.get());
    }
    closedir(dirp);
    if (!title.empty()) {
@@ -695,11 +695,9 @@ int dump_file_from_fd(const char *title, const char *path, int fd) {
    int flags = fcntl(fd, F_GETFL);
    if (flags == -1) {
        printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
        close(fd);
        return -1;
    } else if (!(flags & O_NONBLOCK)) {
        printf("*** %s: fd must have O_NONBLOCK set.\n", path);
        close(fd);
        return -1;
    }
    return DumpFileFromFdToFd(title, path, fd, STDOUT_FILENO, PropertiesHelper::IsDryRun());