Loading cmds/dumpstate/dumpstate.c +4 −2 Original line number Original line Diff line number Diff line Loading @@ -64,7 +64,8 @@ static void get_tombstone_fds(tombstone_data_t data[NUM_TOMBSTONES]) { time_t thirty_minutes_ago = time(NULL) - 60*30; time_t thirty_minutes_ago = time(NULL) - 60*30; for (size_t i = 0; i < NUM_TOMBSTONES; i++) { for (size_t i = 0; i < NUM_TOMBSTONES; i++) { snprintf(data[i].name, sizeof(data[i].name), "%s%02zu", TOMBSTONE_FILE_PREFIX, i); snprintf(data[i].name, sizeof(data[i].name), "%s%02zu", TOMBSTONE_FILE_PREFIX, i); int fd = open(data[i].name, O_RDONLY | O_CLOEXEC | O_NOFOLLOW); int fd = TEMP_FAILURE_RETRY(open(data[i].name, O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)); struct stat st; struct stat st; if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode) && if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode) && (time_t) st.st_mtime >= thirty_minutes_ago) { (time_t) st.st_mtime >= thirty_minutes_ago) { Loading Loading @@ -184,7 +185,8 @@ static void dumpstate() { if (!anr_traces_path[0]) { if (!anr_traces_path[0]) { printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n"); printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n"); } else { } else { int fd = open(anr_traces_path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW); int fd = TEMP_FAILURE_RETRY(open(anr_traces_path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)); if (fd < 0) { if (fd < 0) { printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anr_traces_path, strerror(errno)); printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anr_traces_path, strerror(errno)); } else { } else { Loading cmds/dumpstate/dumpstate.h +3 −1 Original line number Original line Diff line number Diff line Loading @@ -31,7 +31,9 @@ typedef void (for_each_userid_func)(int); /* prints the contents of a file */ /* prints the contents of a file */ int dump_file(const char *title, const char *path); int dump_file(const char *title, const char *path); /* prints the contents of the fd */ /* prints the contents of the fd * fd must have been opened with the flag O_NONBLOCK. */ int dump_file_from_fd(const char *title, const char *path, int fd); int dump_file_from_fd(const char *title, const char *path, int fd); /* forks a command and waits for it to finish -- terminate args with NULL */ /* forks a command and waits for it to finish -- terminate args with NULL */ Loading cmds/dumpstate/utils.c +78 −36 Original line number Original line Diff line number Diff line Loading @@ -53,6 +53,12 @@ static const char* native_processes_to_dump[] = { NULL, NULL, }; }; static uint64_t nanotime() { struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); return (uint64_t)ts.tv_sec * NANOS_PER_SEC + ts.tv_nsec; } void for_each_userid(void (*func)(int), const char *header) { void for_each_userid(void (*func)(int), const char *header) { DIR *d; DIR *d; struct dirent *de; struct dirent *de; Loading Loading @@ -98,7 +104,7 @@ static void __for_each_pid(void (*helper)(int, const char *, void *), const char sprintf(cmdpath,"/proc/%d/cmdline", pid); sprintf(cmdpath,"/proc/%d/cmdline", pid); memset(cmdline, 0, sizeof(cmdline)); memset(cmdline, 0, sizeof(cmdline)); if ((fd = open(cmdpath, O_RDONLY)) < 0) { if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY))) < 0) { strcpy(cmdline, "N/A"); strcpy(cmdline, "N/A"); } else { } else { read(fd, cmdline, sizeof(cmdline) - 1); read(fd, cmdline, sizeof(cmdline) - 1); Loading Loading @@ -149,7 +155,7 @@ static void for_each_tid_helper(int pid, const char *cmdline, void *arg) { sprintf(commpath,"/proc/%d/comm", tid); sprintf(commpath,"/proc/%d/comm", tid); memset(comm, 0, sizeof(comm)); memset(comm, 0, sizeof(comm)); if ((fd = open(commpath, O_RDONLY)) < 0) { if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY))) < 0) { strcpy(comm, "N/A"); strcpy(comm, "N/A"); } else { } else { char *c; char *c; Loading Loading @@ -180,7 +186,7 @@ void show_wchan(int pid, int tid, const char *name) { memset(buffer, 0, sizeof(buffer)); memset(buffer, 0, sizeof(buffer)); sprintf(path, "/proc/%d/wchan", tid); sprintf(path, "/proc/%d/wchan", tid); if ((fd = open(path, O_RDONLY)) < 0) { if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY))) < 0) { printf("Failed to open '%s' (%s)\n", path, strerror(errno)); printf("Failed to open '%s' (%s)\n", path, strerror(errno)); return; return; } } Loading Loading @@ -250,22 +256,7 @@ void do_showmap(int pid, const char *name) { run_command(title, 10, SU_PATH, "root", "showmap", arg, NULL); run_command(title, 10, SU_PATH, "root", "showmap", arg, NULL); } } /* prints the contents of a file */ static int _dump_file_from_fd(const char *title, const char *path, int fd) { int dump_file(const char *title, const char *path) { int fd = open(path, O_RDONLY); if (fd < 0) { int err = errno; if (title) printf("------ %s (%s) ------\n", title, path); printf("*** %s: %s\n", path, strerror(err)); if (title) printf("\n"); return -1; } return dump_file_from_fd(title, path, fd); } int dump_file_from_fd(const char *title, const char *path, int fd) { char buffer[32768]; if (title) printf("------ %s (%s", title, path); if (title) printf("------ %s (%s", title, path); if (title) { if (title) { Loading @@ -279,26 +270,76 @@ int dump_file_from_fd(const char *title, const char *path, int fd) { printf(") ------\n"); printf(") ------\n"); } } int newline = 0; bool newline = false; for (;;) { fd_set read_set; int ret = read(fd, buffer, sizeof(buffer)); struct timeval tm; if (ret > 0) { while (1) { newline = (buffer[ret - 1] == '\n'); FD_ZERO(&read_set); ret = fwrite(buffer, ret, 1, stdout); FD_SET(fd, &read_set); /* Timeout if no data is read for 30 seconds. */ tm.tv_sec = 30; tm.tv_usec = 0; uint64_t elapsed = nanotime(); int ret = TEMP_FAILURE_RETRY(select(fd + 1, &read_set, NULL, NULL, &tm)); if (ret == -1) { printf("*** %s: select failed: %s\n", path, strerror(errno)); newline = true; break; } else if (ret == 0) { elapsed = nanotime() - elapsed; printf("*** %s: Timed out after %.3fs\n", path, (float) elapsed / NANOS_PER_SEC); newline = true; break; } else { char buffer[65536]; ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer))); if (bytes_read > 0) { fwrite(buffer, bytes_read, 1, stdout); newline = (buffer[bytes_read-1] == '\n'); } else { if (bytes_read == -1) { printf("*** %s: Failed to read from fd: %s", path, strerror(errno)); newline = true; } } if (ret <= 0) break; break; } } close(fd); } } TEMP_FAILURE_RETRY(close(fd)); if (!newline) printf("\n"); if (!newline) printf("\n"); if (title) printf("\n"); if (title) printf("\n"); return 0; return 0; } } static int64_t nanotime() { /* prints the contents of a file */ struct timespec ts; int dump_file(const char *title, const char *path) { clock_gettime(CLOCK_MONOTONIC, &ts); int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC)); return (int64_t)ts.tv_sec * NANOS_PER_SEC + ts.tv_nsec; if (fd < 0) { int err = errno; if (title) printf("------ %s (%s) ------\n", title, path); printf("*** %s: %s\n", path, strerror(err)); if (title) printf("\n"); return -1; } return _dump_file_from_fd(title, path, fd); } /* fd must have been opened with the flag O_NONBLOCK. With this flag set, * it's possible to avoid issues where opening the file itself can get * stuck. */ 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)); return -1; } else if (!(flags & O_NONBLOCK)) { printf("*** %s: fd must have O_NONBLOCK set.\n", path); return -1; } return _dump_file_from_fd(title, path, fd); } } bool waitpid_with_timeout(pid_t pid, int timeout_seconds, int* status) { bool waitpid_with_timeout(pid_t pid, int timeout_seconds, int* status) { Loading Loading @@ -348,7 +389,7 @@ bool waitpid_with_timeout(pid_t pid, int timeout_seconds, int* status) { /* forks a command and waits for it to finish */ /* forks a command and waits for it to finish */ int run_command(const char *title, int timeout_seconds, const char *command, ...) { int run_command(const char *title, int timeout_seconds, const char *command, ...) { fflush(stdout); fflush(stdout); int64_t start = nanotime(); uint64_t start = nanotime(); pid_t pid = fork(); pid_t pid = fork(); /* handle error case */ /* handle error case */ Loading Loading @@ -550,7 +591,8 @@ const char *dump_traces() { } } /* create a new, empty traces.txt file to receive stack dumps */ /* create a new, empty traces.txt file to receive stack dumps */ int fd = open(traces_path, O_CREAT | O_WRONLY | O_TRUNC | O_NOFOLLOW, 0666); /* -rw-rw-rw- */ int fd = TEMP_FAILURE_RETRY(open(traces_path, O_CREAT | O_WRONLY | O_TRUNC | O_NOFOLLOW, 0666)); /* -rw-rw-rw- */ if (fd < 0) { if (fd < 0) { fprintf(stderr, "%s: %s\n", traces_path, strerror(errno)); fprintf(stderr, "%s: %s\n", traces_path, strerror(errno)); return NULL; return NULL; Loading Loading @@ -600,7 +642,7 @@ const char *dump_traces() { if (!strncmp(data, "/system/bin/app_process", strlen("/system/bin/app_process"))) { if (!strncmp(data, "/system/bin/app_process", strlen("/system/bin/app_process"))) { /* skip zygote -- it won't dump its stack anyway */ /* skip zygote -- it won't dump its stack anyway */ snprintf(path, sizeof(path), "/proc/%d/cmdline", pid); snprintf(path, sizeof(path), "/proc/%d/cmdline", pid); int cfd = open(path, O_RDONLY); int cfd = TEMP_FAILURE_RETRY(open(path, O_RDONLY)); len = read(cfd, data, sizeof(data) - 1); len = read(cfd, data, sizeof(data) - 1); close(cfd); close(cfd); if (len <= 0) { if (len <= 0) { Loading @@ -612,7 +654,7 @@ const char *dump_traces() { } } ++dalvik_found; ++dalvik_found; int64_t start = nanotime(); uint64_t start = nanotime(); if (kill(pid, SIGQUIT)) { if (kill(pid, SIGQUIT)) { fprintf(stderr, "kill(%d, SIGQUIT): %s\n", pid, strerror(errno)); fprintf(stderr, "kill(%d, SIGQUIT): %s\n", pid, strerror(errno)); continue; continue; Loading Loading @@ -642,7 +684,7 @@ const char *dump_traces() { fprintf(stderr, "lseek: %s\n", strerror(errno)); fprintf(stderr, "lseek: %s\n", strerror(errno)); } else { } else { static uint16_t timeout_failures = 0; static uint16_t timeout_failures = 0; int64_t start = nanotime(); uint64_t start = nanotime(); /* If 3 backtrace dumps fail in a row, consider debuggerd dead. */ /* If 3 backtrace dumps fail in a row, consider debuggerd dead. */ if (timeout_failures == 3) { if (timeout_failures == 3) { Loading Loading
cmds/dumpstate/dumpstate.c +4 −2 Original line number Original line Diff line number Diff line Loading @@ -64,7 +64,8 @@ static void get_tombstone_fds(tombstone_data_t data[NUM_TOMBSTONES]) { time_t thirty_minutes_ago = time(NULL) - 60*30; time_t thirty_minutes_ago = time(NULL) - 60*30; for (size_t i = 0; i < NUM_TOMBSTONES; i++) { for (size_t i = 0; i < NUM_TOMBSTONES; i++) { snprintf(data[i].name, sizeof(data[i].name), "%s%02zu", TOMBSTONE_FILE_PREFIX, i); snprintf(data[i].name, sizeof(data[i].name), "%s%02zu", TOMBSTONE_FILE_PREFIX, i); int fd = open(data[i].name, O_RDONLY | O_CLOEXEC | O_NOFOLLOW); int fd = TEMP_FAILURE_RETRY(open(data[i].name, O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)); struct stat st; struct stat st; if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode) && if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode) && (time_t) st.st_mtime >= thirty_minutes_ago) { (time_t) st.st_mtime >= thirty_minutes_ago) { Loading Loading @@ -184,7 +185,8 @@ static void dumpstate() { if (!anr_traces_path[0]) { if (!anr_traces_path[0]) { printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n"); printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n"); } else { } else { int fd = open(anr_traces_path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW); int fd = TEMP_FAILURE_RETRY(open(anr_traces_path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)); if (fd < 0) { if (fd < 0) { printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anr_traces_path, strerror(errno)); printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anr_traces_path, strerror(errno)); } else { } else { Loading
cmds/dumpstate/dumpstate.h +3 −1 Original line number Original line Diff line number Diff line Loading @@ -31,7 +31,9 @@ typedef void (for_each_userid_func)(int); /* prints the contents of a file */ /* prints the contents of a file */ int dump_file(const char *title, const char *path); int dump_file(const char *title, const char *path); /* prints the contents of the fd */ /* prints the contents of the fd * fd must have been opened with the flag O_NONBLOCK. */ int dump_file_from_fd(const char *title, const char *path, int fd); int dump_file_from_fd(const char *title, const char *path, int fd); /* forks a command and waits for it to finish -- terminate args with NULL */ /* forks a command and waits for it to finish -- terminate args with NULL */ Loading
cmds/dumpstate/utils.c +78 −36 Original line number Original line Diff line number Diff line Loading @@ -53,6 +53,12 @@ static const char* native_processes_to_dump[] = { NULL, NULL, }; }; static uint64_t nanotime() { struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); return (uint64_t)ts.tv_sec * NANOS_PER_SEC + ts.tv_nsec; } void for_each_userid(void (*func)(int), const char *header) { void for_each_userid(void (*func)(int), const char *header) { DIR *d; DIR *d; struct dirent *de; struct dirent *de; Loading Loading @@ -98,7 +104,7 @@ static void __for_each_pid(void (*helper)(int, const char *, void *), const char sprintf(cmdpath,"/proc/%d/cmdline", pid); sprintf(cmdpath,"/proc/%d/cmdline", pid); memset(cmdline, 0, sizeof(cmdline)); memset(cmdline, 0, sizeof(cmdline)); if ((fd = open(cmdpath, O_RDONLY)) < 0) { if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY))) < 0) { strcpy(cmdline, "N/A"); strcpy(cmdline, "N/A"); } else { } else { read(fd, cmdline, sizeof(cmdline) - 1); read(fd, cmdline, sizeof(cmdline) - 1); Loading Loading @@ -149,7 +155,7 @@ static void for_each_tid_helper(int pid, const char *cmdline, void *arg) { sprintf(commpath,"/proc/%d/comm", tid); sprintf(commpath,"/proc/%d/comm", tid); memset(comm, 0, sizeof(comm)); memset(comm, 0, sizeof(comm)); if ((fd = open(commpath, O_RDONLY)) < 0) { if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY))) < 0) { strcpy(comm, "N/A"); strcpy(comm, "N/A"); } else { } else { char *c; char *c; Loading Loading @@ -180,7 +186,7 @@ void show_wchan(int pid, int tid, const char *name) { memset(buffer, 0, sizeof(buffer)); memset(buffer, 0, sizeof(buffer)); sprintf(path, "/proc/%d/wchan", tid); sprintf(path, "/proc/%d/wchan", tid); if ((fd = open(path, O_RDONLY)) < 0) { if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY))) < 0) { printf("Failed to open '%s' (%s)\n", path, strerror(errno)); printf("Failed to open '%s' (%s)\n", path, strerror(errno)); return; return; } } Loading Loading @@ -250,22 +256,7 @@ void do_showmap(int pid, const char *name) { run_command(title, 10, SU_PATH, "root", "showmap", arg, NULL); run_command(title, 10, SU_PATH, "root", "showmap", arg, NULL); } } /* prints the contents of a file */ static int _dump_file_from_fd(const char *title, const char *path, int fd) { int dump_file(const char *title, const char *path) { int fd = open(path, O_RDONLY); if (fd < 0) { int err = errno; if (title) printf("------ %s (%s) ------\n", title, path); printf("*** %s: %s\n", path, strerror(err)); if (title) printf("\n"); return -1; } return dump_file_from_fd(title, path, fd); } int dump_file_from_fd(const char *title, const char *path, int fd) { char buffer[32768]; if (title) printf("------ %s (%s", title, path); if (title) printf("------ %s (%s", title, path); if (title) { if (title) { Loading @@ -279,26 +270,76 @@ int dump_file_from_fd(const char *title, const char *path, int fd) { printf(") ------\n"); printf(") ------\n"); } } int newline = 0; bool newline = false; for (;;) { fd_set read_set; int ret = read(fd, buffer, sizeof(buffer)); struct timeval tm; if (ret > 0) { while (1) { newline = (buffer[ret - 1] == '\n'); FD_ZERO(&read_set); ret = fwrite(buffer, ret, 1, stdout); FD_SET(fd, &read_set); /* Timeout if no data is read for 30 seconds. */ tm.tv_sec = 30; tm.tv_usec = 0; uint64_t elapsed = nanotime(); int ret = TEMP_FAILURE_RETRY(select(fd + 1, &read_set, NULL, NULL, &tm)); if (ret == -1) { printf("*** %s: select failed: %s\n", path, strerror(errno)); newline = true; break; } else if (ret == 0) { elapsed = nanotime() - elapsed; printf("*** %s: Timed out after %.3fs\n", path, (float) elapsed / NANOS_PER_SEC); newline = true; break; } else { char buffer[65536]; ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer))); if (bytes_read > 0) { fwrite(buffer, bytes_read, 1, stdout); newline = (buffer[bytes_read-1] == '\n'); } else { if (bytes_read == -1) { printf("*** %s: Failed to read from fd: %s", path, strerror(errno)); newline = true; } } if (ret <= 0) break; break; } } close(fd); } } TEMP_FAILURE_RETRY(close(fd)); if (!newline) printf("\n"); if (!newline) printf("\n"); if (title) printf("\n"); if (title) printf("\n"); return 0; return 0; } } static int64_t nanotime() { /* prints the contents of a file */ struct timespec ts; int dump_file(const char *title, const char *path) { clock_gettime(CLOCK_MONOTONIC, &ts); int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC)); return (int64_t)ts.tv_sec * NANOS_PER_SEC + ts.tv_nsec; if (fd < 0) { int err = errno; if (title) printf("------ %s (%s) ------\n", title, path); printf("*** %s: %s\n", path, strerror(err)); if (title) printf("\n"); return -1; } return _dump_file_from_fd(title, path, fd); } /* fd must have been opened with the flag O_NONBLOCK. With this flag set, * it's possible to avoid issues where opening the file itself can get * stuck. */ 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)); return -1; } else if (!(flags & O_NONBLOCK)) { printf("*** %s: fd must have O_NONBLOCK set.\n", path); return -1; } return _dump_file_from_fd(title, path, fd); } } bool waitpid_with_timeout(pid_t pid, int timeout_seconds, int* status) { bool waitpid_with_timeout(pid_t pid, int timeout_seconds, int* status) { Loading Loading @@ -348,7 +389,7 @@ bool waitpid_with_timeout(pid_t pid, int timeout_seconds, int* status) { /* forks a command and waits for it to finish */ /* forks a command and waits for it to finish */ int run_command(const char *title, int timeout_seconds, const char *command, ...) { int run_command(const char *title, int timeout_seconds, const char *command, ...) { fflush(stdout); fflush(stdout); int64_t start = nanotime(); uint64_t start = nanotime(); pid_t pid = fork(); pid_t pid = fork(); /* handle error case */ /* handle error case */ Loading Loading @@ -550,7 +591,8 @@ const char *dump_traces() { } } /* create a new, empty traces.txt file to receive stack dumps */ /* create a new, empty traces.txt file to receive stack dumps */ int fd = open(traces_path, O_CREAT | O_WRONLY | O_TRUNC | O_NOFOLLOW, 0666); /* -rw-rw-rw- */ int fd = TEMP_FAILURE_RETRY(open(traces_path, O_CREAT | O_WRONLY | O_TRUNC | O_NOFOLLOW, 0666)); /* -rw-rw-rw- */ if (fd < 0) { if (fd < 0) { fprintf(stderr, "%s: %s\n", traces_path, strerror(errno)); fprintf(stderr, "%s: %s\n", traces_path, strerror(errno)); return NULL; return NULL; Loading Loading @@ -600,7 +642,7 @@ const char *dump_traces() { if (!strncmp(data, "/system/bin/app_process", strlen("/system/bin/app_process"))) { if (!strncmp(data, "/system/bin/app_process", strlen("/system/bin/app_process"))) { /* skip zygote -- it won't dump its stack anyway */ /* skip zygote -- it won't dump its stack anyway */ snprintf(path, sizeof(path), "/proc/%d/cmdline", pid); snprintf(path, sizeof(path), "/proc/%d/cmdline", pid); int cfd = open(path, O_RDONLY); int cfd = TEMP_FAILURE_RETRY(open(path, O_RDONLY)); len = read(cfd, data, sizeof(data) - 1); len = read(cfd, data, sizeof(data) - 1); close(cfd); close(cfd); if (len <= 0) { if (len <= 0) { Loading @@ -612,7 +654,7 @@ const char *dump_traces() { } } ++dalvik_found; ++dalvik_found; int64_t start = nanotime(); uint64_t start = nanotime(); if (kill(pid, SIGQUIT)) { if (kill(pid, SIGQUIT)) { fprintf(stderr, "kill(%d, SIGQUIT): %s\n", pid, strerror(errno)); fprintf(stderr, "kill(%d, SIGQUIT): %s\n", pid, strerror(errno)); continue; continue; Loading Loading @@ -642,7 +684,7 @@ const char *dump_traces() { fprintf(stderr, "lseek: %s\n", strerror(errno)); fprintf(stderr, "lseek: %s\n", strerror(errno)); } else { } else { static uint16_t timeout_failures = 0; static uint16_t timeout_failures = 0; int64_t start = nanotime(); uint64_t start = nanotime(); /* If 3 backtrace dumps fail in a row, consider debuggerd dead. */ /* If 3 backtrace dumps fail in a row, consider debuggerd dead. */ if (timeout_failures == 3) { if (timeout_failures == 3) { Loading