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 
     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