1ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate/* 2ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate ** Copyright 2010, The Android Open Source Project 3ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate ** 4ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate ** Licensed under the Apache License, Version 2.0 (the "License"); 5ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate ** you may not use this file except in compliance with the License. 6ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate ** You may obtain a copy of the License at 7ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate ** 8ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate ** http://www.apache.org/licenses/LICENSE-2.0 9ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate ** 10ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate ** Unless required by applicable law or agreed to in writing, software 11ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate ** distributed under the License is distributed on an "AS IS" BASIS, 12ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate ** See the License for the specific language governing permissions and 14ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate ** limitations under the License. 15ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate */ 16ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate 17ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate#define LOG_TAG "Watchdog_N" 18ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate#include <utils/Log.h> 19ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate 20d8689137283bd902edc58d1385273f6941bb3a2fMarco Nelissen#include <sys/stat.h> 21ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate#include <sys/types.h> 22ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate#include <fcntl.h> 23ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate#include <dirent.h> 24ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate#include <string.h> 25ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate#include <errno.h> 26ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate 27ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate#include "jni.h" 28ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate#include "JNIHelp.h" 29ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate#include <android_runtime/AndroidRuntime.h> 30ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate 31ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tatestatic void dumpOneStack(int tid, int outFd) { 32ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate char buf[64]; 33ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate 34ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate snprintf(buf, sizeof(buf), "/proc/%d/stack", tid); 35ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate int stackFd = open(buf, O_RDONLY); 36ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate if (stackFd >= 0) { 37ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate // header for readability 38ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate strncat(buf, ":\n", sizeof(buf) - strlen(buf) - 1); 39ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate write(outFd, buf, strlen(buf)); 40ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate 41ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate // copy the stack dump text 42ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate int nBytes; 43ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate while ((nBytes = read(stackFd, buf, sizeof(buf))) > 0) { 44ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate write(outFd, buf, nBytes); 45ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate } 46ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate 47ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate // footer and done 48ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate write(outFd, "\n", 1); 49ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate close(stackFd); 50ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate } else { 513762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Unable to open stack of tid %d : %d (%s)", tid, errno, strerror(errno)); 52ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate } 53ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate} 54ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate 55ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tatestatic void dumpKernelStacks(JNIEnv* env, jobject clazz, jstring pathStr) { 56ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate char buf[128]; 57ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate DIR* taskdir; 58ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate 596215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block ALOGI("dumpKernelStacks"); 60ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate if (!pathStr) { 61ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate jniThrowException(env, "java/lang/IllegalArgumentException", "Null path"); 62ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate return; 63ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate } 64ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate 65ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate const char *path = env->GetStringUTFChars(pathStr, NULL); 66ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate 6719399f4ed6f407a0e97b9769cd723e77859ea352Marco Nelissen int outFd = open(path, O_WRONLY | O_APPEND | O_CREAT, 6819399f4ed6f407a0e97b9769cd723e77859ea352Marco Nelissen S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); 69ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate if (outFd < 0) { 703762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Unable to open stack dump file: %d (%s)", errno, strerror(errno)); 71ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate goto done; 72ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate } 73ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate 74ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate snprintf(buf, sizeof(buf), "\n----- begin pid %d kernel stacks -----\n", getpid()); 75ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate write(outFd, buf, strlen(buf)); 76ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate 77ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate // look up the list of all threads in this process 78ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate snprintf(buf, sizeof(buf), "/proc/%d/task", getpid()); 79ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate taskdir = opendir(buf); 80ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate if (taskdir != NULL) { 81ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate struct dirent * ent; 82ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate while ((ent = readdir(taskdir)) != NULL) { 83ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate int tid = atoi(ent->d_name); 84ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate if (tid > 0 && tid <= 65535) { 85ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate // dump each stack trace 86ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate dumpOneStack(tid, outFd); 87ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate } 88ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate } 89ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate closedir(taskdir); 90ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate } 91ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate 92ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate snprintf(buf, sizeof(buf), "----- end pid %d kernel stacks -----\n", getpid()); 93ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate write(outFd, buf, strlen(buf)); 94ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate 95ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate close(outFd); 96ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tatedone: 97ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate env->ReleaseStringUTFChars(pathStr, path); 98ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate} 99ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate 100ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate// ---------------------------------------- 101ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate 102ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tatenamespace android { 103ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate 104ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tatestatic const JNINativeMethod g_methods[] = { 105ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate { "native_dumpKernelStacks", "(Ljava/lang/String;)V", (void*)dumpKernelStacks }, 106ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate}; 107ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate 108ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tateint register_android_server_Watchdog(JNIEnv* env) { 109ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate return AndroidRuntime::registerNativeMethods(env, "com/android/server/Watchdog", 110ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate g_methods, NELEM(g_methods)); 111ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate} 112ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate 113ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate} 114