1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <stdbool.h> 18#include <fcntl.h> 19#include <stdio.h> 20#include <stdlib.h> 21#include <string.h> 22#include <sys/types.h> 23#include <sys/socket.h> 24#include <unistd.h> 25 26#include <cutils/debugger.h> 27#include <cutils/sockets.h> 28 29#define LOG_TAG "DEBUG" 30#include <log/log.h> 31 32static int send_request(int sock_fd, void* msg_ptr, size_t msg_len) { 33 int result = 0; 34 if (TEMP_FAILURE_RETRY(write(sock_fd, msg_ptr, msg_len)) != (ssize_t) msg_len) { 35 result = -1; 36 } else { 37 char ack; 38 if (TEMP_FAILURE_RETRY(read(sock_fd, &ack, 1)) != 1) { 39 result = -1; 40 } 41 } 42 return result; 43} 44 45static int make_dump_request(debugger_action_t action, pid_t tid, int timeout_secs) { 46 debugger_msg_t msg; 47 memset(&msg, 0, sizeof(msg)); 48 msg.tid = tid; 49 msg.action = action; 50 51 int sock_fd = socket_local_client(DEBUGGER_SOCKET_NAME, ANDROID_SOCKET_NAMESPACE_ABSTRACT, 52 SOCK_STREAM | SOCK_CLOEXEC); 53 if (sock_fd < 0) { 54 return -1; 55 } 56 57 if (timeout_secs > 0) { 58 struct timeval tm; 59 tm.tv_sec = timeout_secs; 60 tm.tv_usec = 0; 61 if (setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO, &tm, sizeof(tm)) == -1) { 62 ALOGE("WARNING: Cannot set receive timeout value on socket: %s", strerror(errno)); 63 } 64 65 if (setsockopt(sock_fd, SOL_SOCKET, SO_SNDTIMEO, &tm, sizeof(tm)) == -1) { 66 ALOGE("WARNING: Cannot set send timeout value on socket: %s", strerror(errno)); 67 } 68 } 69 70 if (send_request(sock_fd, &msg, sizeof(msg)) < 0) { 71 close(sock_fd); 72 return -1; 73 } 74 75 return sock_fd; 76} 77 78int dump_backtrace_to_file(pid_t tid, int fd) { 79 return dump_backtrace_to_file_timeout(tid, fd, 0); 80} 81 82int dump_backtrace_to_file_timeout(pid_t tid, int fd, int timeout_secs) { 83 int sock_fd = make_dump_request(DEBUGGER_ACTION_DUMP_BACKTRACE, tid, timeout_secs); 84 if (sock_fd < 0) { 85 return -1; 86 } 87 88 /* Write the data read from the socket to the fd. */ 89 int result = 0; 90 char buffer[1024]; 91 ssize_t n; 92 while ((n = TEMP_FAILURE_RETRY(read(sock_fd, buffer, sizeof(buffer)))) > 0) { 93 if (TEMP_FAILURE_RETRY(write(fd, buffer, n)) != n) { 94 result = -1; 95 break; 96 } 97 } 98 close(sock_fd); 99 return result; 100} 101 102int dump_tombstone(pid_t tid, char* pathbuf, size_t pathlen) { 103 return dump_tombstone_timeout(tid, pathbuf, pathlen, 0); 104} 105 106int dump_tombstone_timeout(pid_t tid, char* pathbuf, size_t pathlen, int timeout_secs) { 107 int sock_fd = make_dump_request(DEBUGGER_ACTION_DUMP_TOMBSTONE, tid, timeout_secs); 108 if (sock_fd < 0) { 109 return -1; 110 } 111 112 /* Read the tombstone file name. */ 113 char buffer[100]; /* This is larger than the largest tombstone path. */ 114 int result = 0; 115 ssize_t n = TEMP_FAILURE_RETRY(read(sock_fd, buffer, sizeof(buffer) - 1)); 116 if (n <= 0) { 117 result = -1; 118 } else { 119 if (pathbuf && pathlen) { 120 if (n >= (ssize_t) pathlen) { 121 n = pathlen - 1; 122 } 123 buffer[n] = '\0'; 124 memcpy(pathbuf, buffer, n + 1); 125 } 126 } 127 close(sock_fd); 128 return result; 129} 130