Plumb tombstoned connections through PALette.
This removes APEX internal dependencies on libtombstoned_client and
libcutils.
Test: art/build/apex/runtests.sh
Test: adb shell killall -QUIT system_server; check tombstoned report in /data/anr
Test: Make /data nearly full; adb shell killall -QUIT system_server; check
that the report in /data/anr has zero length and that the stack traces are
sent to logcat instead
Bug: 130025619
Change-Id: I93dae3729c0e4de9e32b942e6c85915b56d8114a
diff --git a/build/apex/art_apex_test.py b/build/apex/art_apex_test.py
index b93a705..4fc102a 100755
--- a/build/apex/art_apex_test.py
+++ b/build/apex/art_apex_test.py
@@ -450,9 +450,6 @@
self._checker.check_optional_native_library('libclang_rt.hwasan*')
self._checker.check_optional_native_library('libclang_rt.ubsan*')
- # TODO(b/130025619): Get rid of this dependency.
- self._checker.check_native_library('libcutils')
-
class ReleaseTargetChecker:
def __init__(self, checker):
@@ -497,7 +494,6 @@
self._checker.check_native_library('libicui18n')
self._checker.check_native_library('libicuuc')
self._checker.check_native_library('libpac')
- self._checker.check_native_library('libtombstoned_client')
self._checker.check_native_library('libz')
# TODO(b/124293228): Cuttlefish puts ARM libs in a lib/arm subdirectory.
diff --git a/libartpalette/Android.bp b/libartpalette/Android.bp
index 3e7354b..75bf97c 100644
--- a/libartpalette/Android.bp
+++ b/libartpalette/Android.bp
@@ -32,9 +32,11 @@
srcs: ["system/palette_android.cc",],
header_libs: ["libbase_headers"],
shared_libs: [
+ "libbase",
"libcutils",
"liblog",
"libprocessgroup",
+ "libtombstoned_client",
],
},
host: {
diff --git a/libartpalette/apex/palette.cc b/libartpalette/apex/palette.cc
index 0b391f8..1821a17 100644
--- a/libartpalette/apex/palette.cc
+++ b/libartpalette/apex/palette.cc
@@ -125,6 +125,11 @@
return m(tid, java_priority);
}
+enum PaletteStatus PaletteTombstonedMessage(/*in*/const char* msg, size_t msg_len) {
+ PaletteTombstonedMessageMethod m = PaletteLoader::Instance().GetPaletteTombstonedMessageMethod();
+ return m(msg, msg_len);
+}
+
enum PaletteStatus PaletteTraceEnabled(/*out*/int32_t* enabled) {
PaletteTraceEnabledMethod m = PaletteLoader::Instance().GetPaletteTraceEnabledMethod();
return m(enabled);
diff --git a/libartpalette/include/palette/palette_method_list.h b/libartpalette/include/palette/palette_method_list.h
index dc4ec52..3e730fd 100644
--- a/libartpalette/include/palette/palette_method_list.h
+++ b/libartpalette/include/palette/palette_method_list.h
@@ -17,6 +17,7 @@
#ifndef ART_LIBARTPALETTE_INCLUDE_PALETTE_PALETTE_METHOD_LIST_H_
#define ART_LIBARTPALETTE_INCLUDE_PALETTE_PALETTE_METHOD_LIST_H_
+#include <stddef.h>
#include <stdint.h>
// Methods in version 1 API
@@ -24,6 +25,7 @@
M(PaletteGetVersion, /*out*/int32_t* version) \
M(PaletteSchedSetPriority, int32_t tid, int32_t java_priority) \
M(PaletteSchedGetPriority, int32_t tid, /*out*/int32_t* java_priority) \
+ M(PaletteTombstonedMessage, const char* msg, size_t msg_len) \
M(PaletteTraceEnabled, /*out*/int32_t* enabled) \
M(PaletteTraceBegin, const char* name) \
M(PaletteTraceEnd) \
diff --git a/libartpalette/libartpalette.map.txt b/libartpalette/libartpalette.map.txt
index 0920835..78b33ac 100644
--- a/libartpalette/libartpalette.map.txt
+++ b/libartpalette/libartpalette.map.txt
@@ -20,6 +20,7 @@
PaletteGetVersion;
PaletteSchedSetPriority;
PaletteSchedGetPriority;
+ PaletteTombstonedMessage;
PaletteTraceEnabled;
PaletteTraceBegin;
PaletteTraceEnd;
diff --git a/libartpalette/system/palette_android.cc b/libartpalette/system/palette_android.cc
index aed3862..801f334 100644
--- a/libartpalette/system/palette_android.cc
+++ b/libartpalette/system/palette_android.cc
@@ -25,11 +25,13 @@
#include <mutex>
+#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/macros.h>
#include <cutils/sched_policy.h>
#include <cutils/trace.h>
#include <log/event_tag_map.h>
+#include <tombstoned/tombstoned.h>
#include <utils/Thread.h>
#include "palette_system.h"
@@ -104,6 +106,44 @@
return PaletteStatus::kOkay;
}
+enum PaletteStatus PaletteTombstonedMessage(/*in*/const char* msg, size_t msg_len) {
+ android::base::unique_fd tombstone_fd;
+ android::base::unique_fd output_fd;
+ if (!tombstoned_connect(getpid(), &tombstone_fd, &output_fd, kDebuggerdJavaBacktrace)) {
+ return PaletteStatus::kCheckErrno;
+ }
+
+ bool success = true;
+ if (!android::base::WriteFully(output_fd, msg, msg_len)) {
+ LOG(ERROR) << "Failed to write tombstoned output: " << strerror(errno);
+ success = false;
+ } else if (TEMP_FAILURE_RETRY(fsync(output_fd)) == -1) {
+ LOG(ERROR) << "Failed to fsync tombstoned output: " << strerror(errno);
+ success = false;
+ } else if (close(output_fd.release()) == -1) {
+ // Shouldn't retry close after EINTR because the fd has been closed anyway,
+ // but don't count it as a failure either.
+ if (errno != EINTR) {
+ LOG(ERROR) << "Failed to close tombstoned output: " << strerror(errno);
+ success = false;
+ }
+ }
+
+ if (!success) {
+ int saved_errno = errno;
+ TEMP_FAILURE_RETRY(ftruncate(output_fd, 0));
+ TEMP_FAILURE_RETRY(fsync(output_fd));
+ close(output_fd.release());
+ errno = saved_errno;
+ }
+
+ if (!tombstoned_notify_completion(tombstone_fd)) {
+ success = false;
+ }
+
+ return success ? PaletteStatus::kOkay : PaletteStatus::kCheckErrno;
+}
+
enum PaletteStatus PaletteTraceEnabled(/*out*/int32_t* enabled) {
*enabled = (ATRACE_ENABLED() != 0) ? 1 : 0;
return PaletteStatus::kOkay;
diff --git a/libartpalette/system/palette_fake.cc b/libartpalette/system/palette_fake.cc
index 0961e77..07a54df 100644
--- a/libartpalette/system/palette_fake.cc
+++ b/libartpalette/system/palette_fake.cc
@@ -52,6 +52,11 @@
return PaletteStatus::kOkay;
}
+enum PaletteStatus PaletteTombstonedMessage(/*in*/ const char* msg ATTRIBUTE_UNUSED,
+ size_t msg_len ATTRIBUTE_UNUSED) {
+ return PaletteStatus::kOkay;
+}
+
enum PaletteStatus PaletteTraceEnabled(/*out*/int32_t* enabled) {
*enabled = 0;
return PaletteStatus::kOkay;
diff --git a/runtime/Android.bp b/runtime/Android.bp
index d73d93f..4dc1e5a 100644
--- a/runtime/Android.bp
+++ b/runtime/Android.bp
@@ -342,7 +342,6 @@
],
shared_libs: [
"libdl_android",
- "libtombstoned_client",
],
static_libs: [
"libz", // For adler32.
@@ -417,11 +416,6 @@
libart_static_cc_defaults {
name: "libart_static_base_defaults",
- target: {
- android: {
- static_libs: ["libtombstoned_client_static"],
- },
- },
static_libs: [
"libartpalette",
"libbacktrace",
diff --git a/runtime/signal_catcher.cc b/runtime/signal_catcher.cc
index 38ea9cc..1aa8487 100644
--- a/runtime/signal_catcher.cc
+++ b/runtime/signal_catcher.cc
@@ -16,10 +16,11 @@
#include "signal_catcher.h"
+#include <csignal>
+#include <cstdlib>
+#include <cstring>
#include <fcntl.h>
#include <pthread.h>
-#include <signal.h>
-#include <stdlib.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
@@ -29,20 +30,15 @@
#include <android-base/stringprintf.h>
-#if defined(ART_TARGET_ANDROID)
-#include <tombstoned/tombstoned.h>
-#endif
-
#include "arch/instruction_set.h"
-#include "base/file_utils.h"
#include "base/logging.h" // For GetCmdLine.
#include "base/os.h"
#include "base/time_utils.h"
-#include "base/unix_file/fd_file.h"
#include "base/utils.h"
#include "class_linker.h"
#include "gc/heap.h"
#include "jit/profile_saver.h"
+#include "palette/palette.h"
#include "runtime.h"
#include "scoped_thread_state_change-inl.h"
#include "signal_set.h"
@@ -109,30 +105,14 @@
void SignalCatcher::Output(const std::string& s) {
#if defined(ART_TARGET_ANDROID)
- android::base::unique_fd tombstone_fd;
- android::base::unique_fd output_fd;
- if (!tombstoned_connect(getpid(), &tombstone_fd, &output_fd, kDebuggerdJavaBacktrace)) {
- LOG(INFO) << s;
- return;
- }
-
ScopedThreadStateChange tsc(Thread::Current(), kWaitingForSignalCatcherOutput);
-
- std::unique_ptr<File> file(new File(output_fd.release(), true /* check_usage= */));
- bool success = file->WriteFully(s.data(), s.size());
- if (success) {
- success = file->FlushCloseOrErase() == 0;
- } else {
- file->Erase();
- }
-
- if (success) {
+ PaletteStatus status = PaletteTombstonedMessage(s.data(), s.size());
+ if (status == PaletteStatus::kOkay) {
LOG(INFO) << "Wrote stack traces to tombstoned";
} else {
- PLOG(ERROR) << "Failed to write stack traces to tombstoned";
- }
- if (!tombstoned_notify_completion(tombstone_fd)) {
- PLOG(WARNING) << "Unable to notify tombstoned of dump completion";
+ CHECK(status == PaletteStatus::kCheckErrno);
+ PLOG(ERROR) << "Failed to write stack traces to tombstoned: " << strerror(errno);
+ LOG(INFO) << s;
}
#else
LOG(INFO) << s;