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

Commit 1e633474 authored by Narayan Kamath's avatar Narayan Kamath Committed by Gerrit Code Review
Browse files

Merge "tombstoned: allow intercepts for java traces."

parents 68599f57 a73df601
Loading
Loading
Loading
Loading
+23 −3
Original line number Diff line number Diff line
@@ -11,6 +11,11 @@ cc_defaults {
    local_include_dirs: ["include"],
}

cc_library_headers {
    name: "libdebuggerd_common_headers",
    export_include_dirs: ["common/include"]
}

cc_library_shared {
    name: "libtombstoned_client",
    defaults: ["debuggerd_defaults"],
@@ -19,15 +24,18 @@ cc_library_shared {
        "util.cpp",
    ],

    header_libs: ["libdebuggerd_common_headers"],

    static_libs: [
        "libasync_safe"
        "libasync_safe",
    ],

    shared_libs: [
        "libcutils",
        "libbase",
        "libcutils",
    ],

    export_header_lib_headers: ["libdebuggerd_common_headers"],
    export_include_dirs: ["tombstoned/include"]
}

@@ -40,12 +48,15 @@ cc_library_static {
        "util.cpp",
    ],

    header_libs: ["libdebuggerd_common_headers"],

    whole_static_libs: [
        "libasync_safe",
        "libcutils",
        "libbase",
    ],

    export_header_lib_headers: ["libdebuggerd_common_headers"],
    export_include_dirs: ["tombstoned/include"]
}

@@ -55,11 +66,14 @@ cc_library_static {
    defaults: ["debuggerd_defaults"],
    srcs: ["handler/debuggerd_handler.cpp"],

    header_libs: ["libdebuggerd_common_headers"],

    whole_static_libs: [
        "libasync_safe",
        "libdebuggerd",
    ],

    export_header_lib_headers: ["libdebuggerd_common_headers"],
    export_include_dirs: ["include"],
}

@@ -107,11 +121,14 @@ cc_library {
        "util.cpp",
    ],

    header_libs: ["libdebuggerd_common_headers"],

    shared_libs: [
        "libbase",
        "libcutils",
    ],

    export_header_lib_headers: ["libdebuggerd_common_headers"],
    export_include_dirs: ["include"],
}

@@ -191,7 +208,8 @@ cc_test {
        "libbase",
        "libcutils",
        "libdebuggerd_client",
        "liblog"
        "liblog",
        "libnativehelper"
    ],

    static_libs: [
@@ -271,6 +289,8 @@ cc_binary {
    ],
    defaults: ["debuggerd_defaults"],

    header_libs: ["libdebuggerd_common_headers"],

    static_libs: [
        "libbase",
        "libcutils",
+14 −12
Original line number Diff line number Diff line
@@ -40,10 +40,12 @@ using namespace std::chrono_literals;

using android::base::unique_fd;

static bool send_signal(pid_t pid, bool backtrace) {
static bool send_signal(pid_t pid, const DebuggerdDumpType dump_type) {
  const int signal = (dump_type == kDebuggerdJavaBacktrace) ? SIGQUIT : DEBUGGER_SIGNAL;
  sigval val;
  val.sival_int = backtrace;
  if (sigqueue(pid, DEBUGGER_SIGNAL, val) != 0) {
  val.sival_int = (dump_type == kDebuggerdNativeBacktrace) ? 1 : 0;

  if (sigqueue(pid, signal, val) != 0) {
    PLOG(ERROR) << "libdebuggerd_client: failed to send signal to pid " << pid;
    return false;
  }
@@ -58,8 +60,8 @@ static void populate_timeval(struct timeval* tv, const Duration& duration) {
  tv->tv_usec = static_cast<long>(microseconds.count());
}

bool debuggerd_trigger_dump(pid_t pid, unique_fd output_fd, DebuggerdDumpType dump_type,
                            unsigned int timeout_ms) {
bool debuggerd_trigger_dump(pid_t pid, DebuggerdDumpType dump_type, unsigned int timeout_ms,
                            unique_fd output_fd) {
  LOG(INFO) << "libdebuggerd_client: started dumping process " << pid;
  unique_fd sockfd;
  const auto end = std::chrono::steady_clock::now() + std::chrono::milliseconds(timeout_ms);
@@ -102,7 +104,7 @@ bool debuggerd_trigger_dump(pid_t pid, unique_fd output_fd, DebuggerdDumpType du
    return false;
  }

  InterceptRequest req = {.pid = pid };
  InterceptRequest req = {.pid = pid, .dump_type = dump_type};
  if (!set_timeout(sockfd)) {
    PLOG(ERROR) << "libdebugger_client: failed to set timeout";
    return false;
@@ -140,8 +142,7 @@ bool debuggerd_trigger_dump(pid_t pid, unique_fd output_fd, DebuggerdDumpType du
    return false;
  }

  bool backtrace = dump_type == kDebuggerdBacktrace;
  if (!send_signal(pid, backtrace)) {
  if (!send_signal(pid, dump_type)) {
    return false;
  }

@@ -210,15 +211,16 @@ bool debuggerd_trigger_dump(pid_t pid, unique_fd output_fd, DebuggerdDumpType du
  return true;
}

int dump_backtrace_to_file(pid_t tid, int fd) {
  return dump_backtrace_to_file_timeout(tid, fd, 0);
int dump_backtrace_to_file(pid_t tid, DebuggerdDumpType dump_type, int fd) {
  return dump_backtrace_to_file_timeout(tid, dump_type, 0, fd);
}

int dump_backtrace_to_file_timeout(pid_t tid, int fd, int timeout_secs) {
int dump_backtrace_to_file_timeout(pid_t tid, DebuggerdDumpType dump_type, int timeout_secs,
                                   int fd) {
  android::base::unique_fd copy(dup(fd));
  if (copy == -1) {
    return -1;
  }
  int timeout_ms = timeout_secs > 0 ? timeout_secs * 1000 : 0;
  return debuggerd_trigger_dump(tid, std::move(copy), kDebuggerdBacktrace, timeout_ms) ? 0 : -1;
  return debuggerd_trigger_dump(tid, dump_type, timeout_ms, std::move(copy)) ? 0 : -1;
}
+4 −2
Original line number Diff line number Diff line
@@ -67,7 +67,8 @@ TEST(debuggerd_client, race) {
  // Wait for a bit to let the child spawn all of its threads.
  std::this_thread::sleep_for(250ms);

  ASSERT_TRUE(debuggerd_trigger_dump(forkpid, std::move(pipe_write), kDebuggerdBacktrace, 10000));
  ASSERT_TRUE(
      debuggerd_trigger_dump(forkpid, kDebuggerdNativeBacktrace, 10000, std::move(pipe_write)));
  // Immediately kill the forked child, to make sure that the dump didn't return early.
  ASSERT_EQ(0, kill(forkpid, SIGKILL)) << strerror(errno);

@@ -107,5 +108,6 @@ TEST(debuggerd_client, no_timeout) {

  unique_fd output_read, output_write;
  ASSERT_TRUE(Pipe(&output_read, &output_write));
  ASSERT_TRUE(debuggerd_trigger_dump(forkpid, std::move(output_write), kDebuggerdBacktrace, 0));
  ASSERT_TRUE(
      debuggerd_trigger_dump(forkpid, kDebuggerdNativeBacktrace, 0, std::move(output_write)));
}
+49 −0
Original line number Diff line number Diff line
#pragma once

/*
 * Copyright 2017, The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <sys/types.h>

#include <ostream>

enum DebuggerdDumpType : uint8_t {
  kDebuggerdNativeBacktrace,
  kDebuggerdTombstone,
  kDebuggerdJavaBacktrace,
  kDebuggerdAnyIntercept
};

inline std::ostream& operator<<(std::ostream& stream, const DebuggerdDumpType& rhs) {
  switch (rhs) {
    case kDebuggerdNativeBacktrace:
      stream << "kDebuggerdNativeBacktrace";
      break;
    case kDebuggerdTombstone:
      stream << "kDebuggerdTombstone";
      break;
    case kDebuggerdJavaBacktrace:
      stream << "kDebuggerdJavaBacktrace";
      break;
    case kDebuggerdAnyIntercept:
      stream << "kDebuggerdAnyIntercept";
      break;
    default:
      stream << "[unknown]";
  }

  return stream;
}
+12 −5
Original line number Diff line number Diff line
@@ -150,13 +150,13 @@ static void signal_handler(int) {
  _exit(1);
}

static void abort_handler(pid_t target, const bool& tombstoned_connected,
static void abort_handler(pid_t target, const bool tombstoned_connected,
                          unique_fd& tombstoned_socket, unique_fd& output_fd,
                          const char* abort_msg) {
  // If we abort before we get an output fd, contact tombstoned to let any
  // potential listeners know that we failed.
  if (!tombstoned_connected) {
    if (!tombstoned_connect(target, &tombstoned_socket, &output_fd)) {
    if (!tombstoned_connect(target, &tombstoned_socket, &output_fd, kDebuggerdAnyIntercept)) {
      // We failed to connect, not much we can do.
      LOG(ERROR) << "failed to connected to tombstoned to report failure";
      _exit(1);
@@ -207,12 +207,14 @@ int main(int argc, char** argv) {
  action.sa_handler = signal_handler;
  debuggerd_register_handlers(&action);

  if (argc != 3) {
  if (argc != 4) {
    LOG(FATAL) << "Wrong number of args: " << argc << " (expected 4)";
    return 1;
  }

  pid_t main_tid;
  pid_t pseudothread_tid;
  int dump_type;

  if (!android::base::ParseInt(argv[1], &main_tid, 1, std::numeric_limits<pid_t>::max())) {
    LOG(FATAL) << "invalid main tid: " << argv[1];
@@ -222,6 +224,10 @@ int main(int argc, char** argv) {
    LOG(FATAL) << "invalid pseudothread tid: " << argv[2];
  }

  if (!android::base::ParseInt(argv[3], &dump_type, 0, 1)) {
    LOG(FATAL) << "invalid requested dump type: " << argv[3];
  }

  if (target == 1) {
    LOG(FATAL) << "target died before we could attach (received main tid = " << main_tid << ")";
  }
@@ -305,8 +311,9 @@ int main(int argc, char** argv) {
  // Drop our capabilities now that we've attached to the threads we care about.
  drop_capabilities();

  LOG(INFO) << "obtaining output fd from tombstoned";
  tombstoned_connected = tombstoned_connect(target, &tombstoned_socket, &output_fd);
  const DebuggerdDumpType dump_type_enum = static_cast<DebuggerdDumpType>(dump_type);
  LOG(INFO) << "obtaining output fd from tombstoned, type: " << dump_type_enum;
  tombstoned_connected = tombstoned_connect(target, &tombstoned_socket, &output_fd, dump_type_enum);

  // Write a '\1' to stdout to tell the crashing process to resume.
  // It also restores the value of PR_SET_DUMPABLE at this point.
Loading