From 7e2e6a5add901a2a74e65cadb1beebb05e9abaeb Mon Sep 17 00:00:00 2001 From: Adrian Szyndela Date: Tue, 13 Dec 2016 14:43:06 +0100 Subject: [PATCH] crash-stack: work around hanging up on 'D' processes Processes in uninterruptible sleep state ('D' status in ps) cannot be ptraced until they leave the state. To prevent hanging up of crash-stack, we check the target process state. If it is 'D', then we give up ptracing it, and instead print the information from /proc//wchan, /proc//syscall and /proc//stack. Change-Id: I82644051a5499c42db2a8e51a7af98693e8da363 --- src/crash-stack/crash-stack.c | 72 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/src/crash-stack/crash-stack.c b/src/crash-stack/crash-stack.c index ef1814c..694f26c 100644 --- a/src/crash-stack/crash-stack.c +++ b/src/crash-stack/crash-stack.c @@ -290,6 +290,65 @@ void __find_symbol_in_elf(ProcInfo *proc_info, Dwarf_Addr mapping_start) close(fd); } +static int __attachable(pid_t pid) +{ + /* read /proc//stat */ + char buf[20]; + FILE *f; + char status; + + snprintf(buf, sizeof(buf), "/proc/%d/stat", pid); + + f = fopen(buf, "r"); + if (NULL == f) + return -1; + + /* check if status is D */ + if (fscanf(f, "%*d %*s %c", &status) != 1) + return -1; + + fclose(f); + + return status != 'D'; +} + +static void __print_proc_file(pid_t pid, const char *name) +{ + char buf[1024]; + FILE *f; + int r; + + snprintf(buf, sizeof(buf), "/proc/%d/%s", pid, name); + + fprintf(outputfile, "%s:\n", buf); + + f = fopen(buf, "r"); + if (NULL == f) + { + fprintf(errfile, "Failed to open %s: %m\n", buf); + return; + } + + while ((r = fread(buf, 1, sizeof(buf), f)) > 0) + { + fwrite(buf, r, 1, outputfile); + } + + fclose(f); + + fprintf(outputfile, "\n"); +} + +static void __print_not_attachable_process_info(pid_t pid) +{ + fprintf(outputfile, "ERROR: can't attach to process %d - process is in uninterruptible sleep state\n", pid); + fprintf(outputfile, "Giving some /proc info instead:\n\n"); + __print_proc_file(pid, "wchan"); + fprintf(outputfile, "\n"); + __print_proc_file(pid, "syscall"); + __print_proc_file(pid, "stack"); +} + /** * @brief Opens libdwfl for using with live process * @@ -301,6 +360,19 @@ static Dwfl *__open_dwfl_with_pid(pid_t pid, pid_t tid) int status; pid_t stopped_pid; + status = __attachable(pid); + if (-1 == status) + { + fprintf(errfile, "failed to read /proc/%d/stat: %m\n", pid); + return NULL; + } + + if (!status) + { + __print_not_attachable_process_info(pid); + return NULL; + } + if (ptrace(PTRACE_SEIZE, tid, NULL, PTRACE_O_TRACEEXIT) != 0) { fprintf(errfile, "PTRACE_SEIZE failed on TID %d: %m\n", tid); return NULL; -- 2.7.4