crash_dump: print the identity of tracers.
Instead of printing a useless "ptrace attach failed: strerror(EPERM)" message, print the name and pid of a competing tracer when we fail to attach because a process is already being ptraced. Bug: http://b/31531918 Test: debuggerd_test32, debuggerd_test64 on aosp_angler Test: strace -p `pidof surfaceflinger`; debuggerd -b surfaceflinger Change-Id: Ifd3f80fe03de30ff38c0e0068560a7b12875f29d
This commit is contained in:
parent
de6b44aa0e
commit
fd13bf0dcd
|
@ -79,9 +79,27 @@ static bool pid_contains_tid(int pid_proc_fd, pid_t tid) {
|
|||
return fstatat(pid_proc_fd, task_path.c_str(), &st, 0) == 0;
|
||||
}
|
||||
|
||||
static pid_t get_tracer(pid_t tracee) {
|
||||
// Check to see if the thread is being ptraced by another process.
|
||||
android::procinfo::ProcessInfo process_info;
|
||||
if (android::procinfo::GetProcessInfo(tracee, &process_info)) {
|
||||
return process_info.tracer;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Attach to a thread, and verify that it's still a member of the given process
|
||||
static bool ptrace_seize_thread(int pid_proc_fd, pid_t tid, std::string* error) {
|
||||
if (ptrace(PTRACE_SEIZE, tid, 0, 0) != 0) {
|
||||
if (errno == EPERM) {
|
||||
pid_t tracer = get_tracer(tid);
|
||||
if (tracer != -1) {
|
||||
*error = StringPrintf("failed to attach to thread %d, already traced by %d (%s)", tid,
|
||||
tracer, get_process_name(tracer).c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
*error = StringPrintf("failed to attach to thread %d: %s", tid, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -16,10 +16,11 @@
|
|||
|
||||
#include <err.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/capability.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <regex>
|
||||
|
@ -569,6 +570,40 @@ TEST_F(CrasherTest, fake_pid) {
|
|||
ASSERT_BACKTRACE_FRAME(result, "tgkill");
|
||||
}
|
||||
|
||||
TEST_F(CrasherTest, competing_tracer) {
|
||||
int intercept_result;
|
||||
unique_fd output_fd;
|
||||
StartProcess([]() {
|
||||
while (true) {
|
||||
}
|
||||
});
|
||||
|
||||
StartIntercept(&output_fd);
|
||||
FinishCrasher();
|
||||
|
||||
ASSERT_EQ(0, ptrace(PTRACE_SEIZE, crasher_pid, 0, 0));
|
||||
ASSERT_EQ(0, kill(crasher_pid, SIGABRT));
|
||||
|
||||
int status;
|
||||
ASSERT_EQ(crasher_pid, waitpid(crasher_pid, &status, 0));
|
||||
ASSERT_TRUE(WIFSTOPPED(status));
|
||||
ASSERT_EQ(SIGABRT, WSTOPSIG(status));
|
||||
|
||||
ASSERT_EQ(0, ptrace(PTRACE_CONT, crasher_pid, 0, SIGABRT));
|
||||
FinishIntercept(&intercept_result);
|
||||
ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
|
||||
|
||||
std::string result;
|
||||
ConsumeFd(std::move(output_fd), &result);
|
||||
std::string regex = R"(failed to attach to thread \d+, already traced by )";
|
||||
regex += std::to_string(gettid());
|
||||
regex += R"( \(.+debuggerd_test)";
|
||||
ASSERT_MATCH(result, regex.c_str());
|
||||
|
||||
ASSERT_EQ(0, ptrace(PTRACE_DETACH, crasher_pid, 0, SIGABRT));
|
||||
AssertDeath(SIGABRT);
|
||||
}
|
||||
|
||||
TEST(crash_dump, zombie) {
|
||||
pid_t forkpid = fork();
|
||||
|
||||
|
|
Loading…
Reference in New Issue