summaryrefslogtreecommitdiffstats
path: root/debuggerd/utility.cpp
diff options
context:
space:
mode:
authorChristopher Ferris <cferris@google.com>2014-01-10 16:05:12 -0800
committerChristopher Ferris <cferris@google.com>2014-01-10 16:05:12 -0800
commitd607495b892fe6ffa1cd30eaad114eec97d77681 (patch)
tree76e9a713373ced70dd17c884d499b83c5e54249e /debuggerd/utility.cpp
parent261ff50e32b2b2a41bd3993c37abb5a9a94e431b (diff)
downloadsystem_core-d607495b892fe6ffa1cd30eaad114eec97d77681.zip
system_core-d607495b892fe6ffa1cd30eaad114eec97d77681.tar.gz
system_core-d607495b892fe6ffa1cd30eaad114eec97d77681.tar.bz2
Move to C++ for debuggerd.
This is part 1, only including the bare minimum changes because our diff tool doesn't easily show differences when a file moves. This also breaks it into a small chunk in case some other changes break things, as unlikely as I think that will be. Change-Id: Ib7a3e7a2cc1ac574d15b65fda23813ebcf5d31af
Diffstat (limited to 'debuggerd/utility.cpp')
-rw-r--r--debuggerd/utility.cpp130
1 files changed, 130 insertions, 0 deletions
diff --git a/debuggerd/utility.cpp b/debuggerd/utility.cpp
new file mode 100644
index 0000000..41be982
--- /dev/null
+++ b/debuggerd/utility.cpp
@@ -0,0 +1,130 @@
+/* system/debuggerd/utility.c
+**
+** Copyright 2008, 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 <stddef.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <signal.h>
+#include <log/logd.h>
+#include <sys/ptrace.h>
+#include <sys/wait.h>
+#include <arpa/inet.h>
+#include <assert.h>
+
+#include "utility.h"
+
+const int sleep_time_usec = 50000; /* 0.05 seconds */
+const int max_total_sleep_usec = 10000000; /* 10 seconds */
+
+static int write_to_am(int fd, const char* buf, int len) {
+ int to_write = len;
+ while (to_write > 0) {
+ int written = TEMP_FAILURE_RETRY( write(fd, buf + len - to_write, to_write) );
+ if (written < 0) {
+ /* hard failure */
+ LOG("AM write failure (%d / %s)\n", errno, strerror(errno));
+ return -1;
+ }
+ to_write -= written;
+ }
+ return len;
+}
+
+void _LOG(log_t* log, int scopeFlags, const char *fmt, ...) {
+ char buf[512];
+ bool want_tfd_write;
+ bool want_log_write;
+ bool want_amfd_write;
+ int len = 0;
+
+ va_list ap;
+ va_start(ap, fmt);
+
+ // where is the information going to go?
+ want_tfd_write = log && log->tfd >= 0;
+ want_log_write = IS_AT_FAULT(scopeFlags) && (!log || !log->quiet);
+ want_amfd_write = IS_AT_FAULT(scopeFlags) && !IS_SENSITIVE(scopeFlags) && log && log->amfd >= 0;
+
+ // if we're going to need the literal string, generate it once here
+ if (want_tfd_write || want_amfd_write) {
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+ len = strlen(buf);
+ }
+
+ if (want_tfd_write) {
+ write(log->tfd, buf, len);
+ }
+
+ if (want_log_write) {
+ // whatever goes to logcat also goes to the Activity Manager
+ __android_log_vprint(ANDROID_LOG_INFO, "DEBUG", fmt, ap);
+ if (want_amfd_write && len > 0) {
+ int written = write_to_am(log->amfd, buf, len);
+ if (written <= 0) {
+ // timeout or other failure on write; stop informing the activity manager
+ log->amfd = -1;
+ }
+ }
+ }
+ va_end(ap);
+}
+
+int wait_for_signal(pid_t tid, int* total_sleep_time_usec) {
+ for (;;) {
+ int status;
+ pid_t n = waitpid(tid, &status, __WALL | WNOHANG);
+ if (n < 0) {
+ if(errno == EAGAIN) continue;
+ LOG("waitpid failed: %s\n", strerror(errno));
+ return -1;
+ } else if (n > 0) {
+ XLOG("waitpid: n=%d status=%08x\n", n, status);
+ if (WIFSTOPPED(status)) {
+ return WSTOPSIG(status);
+ } else {
+ LOG("unexpected waitpid response: n=%d, status=%08x\n", n, status);
+ return -1;
+ }
+ }
+
+ if (*total_sleep_time_usec > max_total_sleep_usec) {
+ LOG("timed out waiting for tid=%d to die\n", tid);
+ return -1;
+ }
+
+ /* not ready yet */
+ XLOG("not ready yet\n");
+ usleep(sleep_time_usec);
+ *total_sleep_time_usec += sleep_time_usec;
+ }
+}
+
+void wait_for_stop(pid_t tid, int* total_sleep_time_usec) {
+ siginfo_t si;
+ while (TEMP_FAILURE_RETRY(ptrace(PTRACE_GETSIGINFO, tid, 0, &si)) < 0 && errno == ESRCH) {
+ if (*total_sleep_time_usec > max_total_sleep_usec) {
+ LOG("timed out waiting for tid=%d to stop\n", tid);
+ break;
+ }
+
+ usleep(sleep_time_usec);
+ *total_sleep_time_usec += sleep_time_usec;
+ }
+}