1/* system/debuggerd/utility.c 2** 3** Copyright 2008, The Android Open Source Project 4** 5** Licensed under the Apache License, Version 2.0 (the "License"); 6** you may not use this file except in compliance with the License. 7** You may obtain a copy of the License at 8** 9** http://www.apache.org/licenses/LICENSE-2.0 10** 11** Unless required by applicable law or agreed to in writing, software 12** distributed under the License is distributed on an "AS IS" BASIS, 13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14** See the License for the specific language governing permissions and 15** limitations under the License. 16*/ 17 18#include <stddef.h> 19#include <stdbool.h> 20#include <stdio.h> 21#include <string.h> 22#include <errno.h> 23#include <unistd.h> 24#include <signal.h> 25#include <log/logd.h> 26#include <sys/ptrace.h> 27#include <sys/wait.h> 28#include <arpa/inet.h> 29#include <assert.h> 30 31#include "utility.h" 32 33const int sleep_time_usec = 50000; /* 0.05 seconds */ 34const int max_total_sleep_usec = 10000000; /* 10 seconds */ 35 36static int write_to_am(int fd, const char* buf, int len) { 37 int to_write = len; 38 while (to_write > 0) { 39 int written = TEMP_FAILURE_RETRY( write(fd, buf + len - to_write, to_write) ); 40 if (written < 0) { 41 /* hard failure */ 42 LOG("AM write failure (%d / %s)\n", errno, strerror(errno)); 43 return -1; 44 } 45 to_write -= written; 46 } 47 return len; 48} 49 50void _LOG(log_t* log, int scopeFlags, const char *fmt, ...) { 51 char buf[512]; 52 bool want_tfd_write; 53 bool want_log_write; 54 bool want_amfd_write; 55 int len = 0; 56 57 va_list ap; 58 va_start(ap, fmt); 59 60 // where is the information going to go? 61 want_tfd_write = log && log->tfd >= 0; 62 want_log_write = IS_AT_FAULT(scopeFlags) && (!log || !log->quiet); 63 want_amfd_write = IS_AT_FAULT(scopeFlags) && !IS_SENSITIVE(scopeFlags) && log && log->amfd >= 0; 64 65 // if we're going to need the literal string, generate it once here 66 if (want_tfd_write || want_amfd_write) { 67 vsnprintf(buf, sizeof(buf), fmt, ap); 68 len = strlen(buf); 69 } 70 71 if (want_tfd_write) { 72 write(log->tfd, buf, len); 73 } 74 75 if (want_log_write) { 76 // whatever goes to logcat also goes to the Activity Manager 77 __android_log_vprint(ANDROID_LOG_INFO, "DEBUG", fmt, ap); 78 if (want_amfd_write && len > 0) { 79 int written = write_to_am(log->amfd, buf, len); 80 if (written <= 0) { 81 // timeout or other failure on write; stop informing the activity manager 82 log->amfd = -1; 83 } 84 } 85 } 86 va_end(ap); 87} 88 89int wait_for_signal(pid_t tid, int* total_sleep_time_usec) { 90 for (;;) { 91 int status; 92 pid_t n = waitpid(tid, &status, __WALL | WNOHANG); 93 if (n < 0) { 94 if(errno == EAGAIN) continue; 95 LOG("waitpid failed: %s\n", strerror(errno)); 96 return -1; 97 } else if (n > 0) { 98 XLOG("waitpid: n=%d status=%08x\n", n, status); 99 if (WIFSTOPPED(status)) { 100 return WSTOPSIG(status); 101 } else { 102 LOG("unexpected waitpid response: n=%d, status=%08x\n", n, status); 103 return -1; 104 } 105 } 106 107 if (*total_sleep_time_usec > max_total_sleep_usec) { 108 LOG("timed out waiting for tid=%d to die\n", tid); 109 return -1; 110 } 111 112 /* not ready yet */ 113 XLOG("not ready yet\n"); 114 usleep(sleep_time_usec); 115 *total_sleep_time_usec += sleep_time_usec; 116 } 117} 118 119void wait_for_stop(pid_t tid, int* total_sleep_time_usec) { 120 siginfo_t si; 121 while (TEMP_FAILURE_RETRY(ptrace(PTRACE_GETSIGINFO, tid, 0, &si)) < 0 && errno == ESRCH) { 122 if (*total_sleep_time_usec > max_total_sleep_usec) { 123 LOG("timed out waiting for tid=%d to stop\n", tid); 124 break; 125 } 126 127 usleep(sleep_time_usec); 128 *total_sleep_time_usec += sleep_time_usec; 129 } 130} 131