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 31const int sleep_time_usec = 50000; /* 0.05 seconds */ 32const int max_total_sleep_usec = 10000000; /* 10 seconds */ 33 34void _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 53int 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 83void 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