Home | History | Annotate | Download | only in debuggerd
      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 #include <arpa/inet.h>
     29 #include <assert.h>
     30 
     31 #include "utility.h"
     32 
     33 const int sleep_time_usec = 50000;         /* 0.05 seconds */
     34 const int max_total_sleep_usec = 10000000; /* 10 seconds */
     35 
     36 static 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 
     50 void _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 
     89 int 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 
    119 void 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