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 <cutils/logd.h> 26 #include <sys/ptrace.h> 27 #include <sys/wait.h> 28 29 #include "utility.h" 30 31 const int sleep_time_usec = 50000; /* 0.05 seconds */ 32 const int max_total_sleep_usec = 10000000; /* 10 seconds */ 33 34 void _LOG(log_t* log, bool in_tombstone_only, const char *fmt, ...) { 35 char buf[512]; 36 37 va_list ap; 38 va_start(ap, fmt); 39 40 if (log && log->tfd >= 0) { 41 int len; 42 vsnprintf(buf, sizeof(buf), fmt, ap); 43 len = strlen(buf); 44 write(log->tfd, buf, len); 45 } 46 47 if (!in_tombstone_only && (!log || !log->quiet)) { 48 __android_log_vprint(ANDROID_LOG_INFO, "DEBUG", fmt, ap); 49 } 50 va_end(ap); 51 } 52 53 int wait_for_signal(pid_t tid, int* total_sleep_time_usec) { 54 for (;;) { 55 int status; 56 pid_t n = waitpid(tid, &status, __WALL | WNOHANG); 57 if (n < 0) { 58 if(errno == EAGAIN) continue; 59 LOG("waitpid failed: %s\n", strerror(errno)); 60 return -1; 61 } else if (n > 0) { 62 XLOG("waitpid: n=%d status=%08x\n", n, status); 63 if (WIFSTOPPED(status)) { 64 return WSTOPSIG(status); 65 } else { 66 LOG("unexpected waitpid response: n=%d, status=%08x\n", n, status); 67 return -1; 68 } 69 } 70 71 if (*total_sleep_time_usec > max_total_sleep_usec) { 72 LOG("timed out waiting for tid=%d to die\n", tid); 73 return -1; 74 } 75 76 /* not ready yet */ 77 XLOG("not ready yet\n"); 78 usleep(sleep_time_usec); 79 *total_sleep_time_usec += sleep_time_usec; 80 } 81 } 82 83 void wait_for_stop(pid_t tid, int* total_sleep_time_usec) { 84 siginfo_t si; 85 while (TEMP_FAILURE_RETRY(ptrace(PTRACE_GETSIGINFO, tid, 0, &si)) < 0 && errno == ESRCH) { 86 if (*total_sleep_time_usec > max_total_sleep_usec) { 87 LOG("timed out waiting for tid=%d to stop\n", tid); 88 break; 89 } 90 91 usleep(sleep_time_usec); 92 *total_sleep_time_usec += sleep_time_usec; 93 } 94 } 95