diff options
Diffstat (limited to 'debuggerd/debuggerd.cpp')
-rw-r--r-- | debuggerd/debuggerd.cpp | 105 |
1 files changed, 14 insertions, 91 deletions
diff --git a/debuggerd/debuggerd.cpp b/debuggerd/debuggerd.cpp index eabbb9abf..b6c2f8a18 100644 --- a/debuggerd/debuggerd.cpp +++ b/debuggerd/debuggerd.cpp @@ -15,21 +15,20 @@ */ #include <dirent.h> +#include <elf.h> #include <errno.h> #include <fcntl.h> #include <pthread.h> #include <signal.h> #include <stdarg.h> #include <stdio.h> -#include <sys/types.h> -#include <time.h> - -#include <elf.h> #include <sys/poll.h> #include <sys/prctl.h> #include <sys/ptrace.h> #include <sys/stat.h> +#include <sys/types.h> #include <sys/wait.h> +#include <time.h> #include <set> @@ -48,6 +47,7 @@ #include "backtrace.h" #include "getevent.h" +#include "signal_sender.h" #include "tombstone.h" #include "utility.h" @@ -422,7 +422,7 @@ static bool perform_dump(const debugger_request_t& request, int fd, int tombston // this we get a lot of "ptrace detach failed: // No such process". *crash_signal = signal; - kill(request.pid, SIGSTOP); + send_signal(request.pid, 0, SIGSTOP); engrave_tombstone(tombstone_fd, backtrace_map, request.pid, request.tid, siblings, signal, request.original_si_code, request.abort_msg_address); break; @@ -451,60 +451,6 @@ static bool drop_privileges() { return true; } -// Fork a process that listens for signals to send, or 0, to exit. -static bool fork_signal_sender(int* out_fd, pid_t* sender_pid, pid_t target_pid) { - int sfd[2]; - if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sfd) != 0) { - ALOGE("debuggerd: failed to create socketpair for signal sender: %s", strerror(errno)); - return false; - } - - pid_t fork_pid = fork(); - if (fork_pid == -1) { - ALOGE("debuggerd: failed to initialize signal sender: fork failed: %s", strerror(errno)); - return false; - } else if (fork_pid == 0) { - close(sfd[1]); - - while (true) { - int signal; - int rc = TEMP_FAILURE_RETRY(read(sfd[0], &signal, sizeof(signal))); - if (rc < 0) { - ALOGE("debuggerd: signal sender failed to read from socket"); - kill(target_pid, SIGKILL); - exit(1); - } else if (rc != sizeof(signal)) { - ALOGE("debuggerd: signal sender read unexpected number of bytes: %d", rc); - kill(target_pid, SIGKILL); - exit(1); - } - - // Report success after sending a signal, or before exiting. - int err = 0; - if (signal != 0) { - if (kill(target_pid, signal) != 0) { - err = errno; - } - } - - if (TEMP_FAILURE_RETRY(write(sfd[0], &err, sizeof(err))) < 0) { - ALOGE("debuggerd: signal sender failed to write: %s", strerror(errno)); - kill(target_pid, SIGKILL); - exit(1); - } - - if (signal == 0) { - exit(0); - } - } - } else { - close(sfd[0]); - *out_fd = sfd[1]; - *sender_pid = fork_pid; - return true; - } -} - static void handle_request(int fd) { ALOGV("handle_request(%d)\n", fd); @@ -585,15 +531,6 @@ static void handle_request(int fd) { // Don't attach to the sibling threads if we want to attach gdb. // Supposedly, it makes the process less reliable. bool attach_gdb = should_attach_gdb(&request); - int signal_fd = -1; - pid_t signal_pid = 0; - - // Fork a process that stays root, and listens on a pipe to pause and resume the target. - if (!fork_signal_sender(&signal_fd, &signal_pid, request.pid)) { - ALOGE("debuggerd: failed to fork signal sender"); - exit(1); - } - if (attach_gdb) { // Open all of the input devices we need to listen for VOLUMEDOWN before dropping privileges. if (init_getevent() != 0) { @@ -603,21 +540,6 @@ static void handle_request(int fd) { } - auto send_signal = [=](int signal) { - int error; - if (TEMP_FAILURE_RETRY(write(signal_fd, &signal, sizeof(signal))) < 0) { - ALOGE("debuggerd: failed to notify signal process: %s", strerror(errno)); - return false; - } else if (TEMP_FAILURE_RETRY(read(signal_fd, &error, sizeof(error))) < 0) { - ALOGE("debuggerd: failed to read response from signal process: %s", strerror(errno)); - return false; - } else if (error != 0) { - errno = error; - return false; - } - return true; - }; - std::set<pid_t> siblings; if (!attach_gdb) { ptrace_siblings(request.pid, request.tid, siblings); @@ -646,7 +568,7 @@ static void handle_request(int fd) { if (attach_gdb) { // Tell the signal process to send SIGSTOP to the target. - if (!send_signal(SIGSTOP)) { + if (!send_signal(request.pid, 0, SIGSTOP)) { ALOGE("debuggerd: failed to stop process for gdb attach: %s", strerror(errno)); attach_gdb = false; } @@ -662,7 +584,7 @@ static void handle_request(int fd) { // Send the signal back to the process if it crashed and we're not waiting for gdb. if (!attach_gdb && request.action == DEBUGGER_ACTION_CRASH) { - if (!send_signal(crash_signal)) { + if (!send_signal(request.pid, request.tid, crash_signal)) { ALOGE("debuggerd: failed to kill process %d: %s", request.pid, strerror(errno)); } } @@ -672,18 +594,13 @@ static void handle_request(int fd) { wait_for_user_action(request); // Tell the signal process to send SIGCONT to the target. - if (!send_signal(SIGCONT)) { + if (!send_signal(request.pid, 0, SIGCONT)) { ALOGE("debuggerd: failed to resume process %d: %s", request.pid, strerror(errno)); } uninit_getevent(); } - if (!send_signal(0)) { - ALOGE("debuggerd: failed to notify signal sender to finish"); - kill(signal_pid, SIGKILL); - } - waitpid(signal_pid, nullptr, 0); exit(!succeeded); } @@ -714,6 +631,12 @@ static int do_server() { SOCK_STREAM | SOCK_CLOEXEC); if (s == -1) return 1; + // Fork a process that stays root, and listens on a pipe to pause and resume the target. + if (!start_signal_sender()) { + ALOGE("debuggerd: failed to fork signal sender"); + return 1; + } + ALOGI("debuggerd: starting\n"); for (;;) { |