/* system/debuggerd/utility.c
**
** Copyright 2008, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
#include <stddef.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <cutils/logd.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include "utility.h"
const int sleep_time_usec = 50000; /* 0.05 seconds */
const int max_total_sleep_usec = 10000000; /* 10 seconds */
void _LOG(log_t* log, bool in_tombstone_only, const char *fmt, ...) {
char buf[512];
va_list ap;
va_start(ap, fmt);
if (log && log->tfd >= 0) {
int len;
vsnprintf(buf, sizeof(buf), fmt, ap);
len = strlen(buf);
write(log->tfd, buf, len);
}
if (!in_tombstone_only && (!log || !log->quiet)) {
__android_log_vprint(ANDROID_LOG_INFO, "DEBUG", fmt, ap);
}
va_end(ap);
}
int wait_for_signal(pid_t tid, int* total_sleep_time_usec) {
for (;;) {
int status;
pid_t n = waitpid(tid, &status, __WALL | WNOHANG);
if (n < 0) {
if(errno == EAGAIN) continue;
LOG("waitpid failed: %s\n", strerror(errno));
return -1;
} else if (n > 0) {
XLOG("waitpid: n=%d status=%08x\n", n, status);
if (WIFSTOPPED(status)) {
return WSTOPSIG(status);
} else {
LOG("unexpected waitpid response: n=%d, status=%08x\n", n, status);
return -1;
}
}
if (*total_sleep_time_usec > max_total_sleep_usec) {
LOG("timed out waiting for tid=%d to die\n", tid);
return -1;
}
/* not ready yet */
XLOG("not ready yet\n");
usleep(sleep_time_usec);
*total_sleep_time_usec += sleep_time_usec;
}
}
void wait_for_stop(pid_t tid, int* total_sleep_time_usec) {
siginfo_t si;
while (TEMP_FAILURE_RETRY(ptrace(PTRACE_GETSIGINFO, tid, 0, &si)) < 0 && errno == ESRCH) {
if (*total_sleep_time_usec > max_total_sleep_usec) {
LOG("timed out waiting for tid=%d to stop\n", tid);
break;
}
usleep(sleep_time_usec);
*total_sleep_time_usec += sleep_time_usec;
}
}