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

Commit 0c22e8b3 authored by Colin Cross's avatar Colin Cross
Browse files

dumpstate: dump all threads in show_wchan

for_each_pid only finds processes and not their threads.  Add
for_each_tid and call it for show_wchan so we can see where all
threads are blocked in the kernel.

Change-Id: Iffb59f7c2933cecf51cdd358a36e19932c2f24c7
parent 7e251273
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -102,7 +102,7 @@ static void dumpstate() {
    run_command("LIST OF OPEN FILES", 10, SU_PATH, "root", "lsof", NULL);

    for_each_pid(do_showmap, "SMAPS OF ALL PROCESSES");
    for_each_pid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
    for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");

    // dump_file("EVENT LOG TAGS", "/etc/event-log-tags");
    run_command("SYSTEM LOG", 20, "logcat", "-v", "threadtime", "-d", "*:v", NULL);
+9 −2
Original line number Diff line number Diff line
@@ -19,10 +19,14 @@

#include <time.h>
#include <unistd.h>
#include <stdbool.h>
#include <stdio.h>

#define SU_PATH "/system/xbin/su"

typedef void (for_each_pid_func)(int, const char *);
typedef void (for_each_tid_func)(int, int, const char *);

/* prints the contents of a file */
int dump_file(const char *title, const char* path);

@@ -42,10 +46,13 @@ pid_t redirect_to_file(FILE *redirect, char *path, int gzip_level);
const char *dump_traces();

/* for each process in the system, run the specified function */
void for_each_pid(void (*func)(int, const char *), const char *header);
void for_each_pid(for_each_pid_func func, const char *header);

/* for each thread in the system, run the specified function */
void for_each_tid(for_each_tid_func func, const char *header);

/* Displays a blocked processes in-kernel wait channel */
void show_wchan(int pid, const char *name);
void show_wchan(int pid, int tid, const char *name);

/* Runs "showmap" for a process */
void do_showmap(int pid, const char *name);
+71 −6
Original line number Diff line number Diff line
@@ -48,7 +48,7 @@ static const char* native_processes_to_dump[] = {
        NULL,
};

void for_each_pid(void (*func)(int, const char *), const char *header) {
static void __for_each_pid(void (*helper)(int, const char *, void *), const char *header, void *arg) {
    DIR *d;
    struct dirent *de;

@@ -73,23 +73,85 @@ void for_each_pid(void (*func)(int, const char *), const char *header) {
        if ((fd = open(cmdpath, O_RDONLY)) < 0) {
            strcpy(cmdline, "N/A");
        } else {
            read(fd, cmdline, sizeof(cmdline));
            read(fd, cmdline, sizeof(cmdline) - 1);
            close(fd);
        }
        helper(pid, cmdline, arg);
    }

    closedir(d);
}

static void for_each_pid_helper(int pid, const char *cmdline, void *arg) {
    for_each_pid_func *func = arg;
    func(pid, cmdline);
}

void for_each_pid(for_each_pid_func func, const char *header) {
    __for_each_pid(for_each_pid_helper, header, func);
}

static void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
    DIR *d;
    struct dirent *de;
    char taskpath[255];
    for_each_tid_func *func = arg;

    sprintf(taskpath, "/proc/%d/task", pid);

    if (!(d = opendir(taskpath))) {
        printf("Failed to open %s (%s)\n", taskpath, strerror(errno));
        return;
    }

    func(pid, pid, cmdline);

    while ((de = readdir(d))) {
        int tid;
        int fd;
        char commpath[255];
        char comm[255];

        if (!(tid = atoi(de->d_name))) {
            continue;
        }

        if (tid == pid)
            continue;

        sprintf(commpath,"/proc/%d/comm", tid);
        memset(comm, 0, sizeof(cmdline));
        if ((fd = open(commpath, O_RDONLY)) < 0) {
            strcpy(comm, "N/A");
        } else {
            char *c;
            read(fd, comm, sizeof(comm) - 1);
            close(fd);

            c = strrchr(comm, '\n');
            if (c) {
                *c = '\0';
            }
        }
        func(pid, tid, comm);
    }

    closedir(d);
}

void show_wchan(int pid, const char *name) {
void for_each_tid(for_each_tid_func func, const char *header) {
    __for_each_pid(for_each_tid_helper, header, func);
}

void show_wchan(int pid, int tid, const char *name) {
    char path[255];
    char buffer[255];
    int fd;
    char name_buffer[255];

    memset(buffer, 0, sizeof(buffer));

    sprintf(path, "/proc/%d/wchan", pid);
    sprintf(path, "/proc/%d/wchan", tid);
    if ((fd = open(path, O_RDONLY)) < 0) {
        printf("Failed to open '%s' (%s)\n", path, strerror(errno));
        return;
@@ -100,7 +162,10 @@ void show_wchan(int pid, const char *name) {
        goto out_close;
    }

    printf("%-7d %-32s %s\n", pid, name, buffer);
    snprintf(name_buffer, sizeof(name_buffer), "%*s%s",
             pid == tid ? 0 : 3, "", name);

    printf("%-7d %-32s %s\n", tid, name_buffer, buffer);

out_close:
    close(fd);