From 0f0ae023a3a53f7c9e254283b50a0099781acb79 Mon Sep 17 00:00:00 2001 From: Dianne Hackborn Date: Tue, 23 Jun 2009 19:21:10 -0700 Subject: [PATCH] Add FileDescriptor variation of startMethodTracing(). This is for bug #1829561 ("am profile" with bad filename kills process), which will allow the am command to take care of opening the file and handing the resulting fd over to the process to be profiled. --- .../src/main/java/dalvik/system/VMDebug.java | 17 ++++++++++++++- vm/Profile.c | 12 ++++++++--- vm/Profile.h | 3 ++- vm/native/dalvik_system_VMDebug.c | 24 ++++++++++++++++------ 4 files changed, 45 insertions(+), 11 deletions(-) diff --git a/libcore/dalvik/src/main/java/dalvik/system/VMDebug.java b/libcore/dalvik/src/main/java/dalvik/system/VMDebug.java index d9f11ce79..efc25d6a2 100644 --- a/libcore/dalvik/src/main/java/dalvik/system/VMDebug.java +++ b/libcore/dalvik/src/main/java/dalvik/system/VMDebug.java @@ -16,6 +16,7 @@ package dalvik.system; +import java.io.FileDescriptor; import java.io.IOException; /** @@ -149,8 +150,22 @@ public final class VMDebug { * @param flags flags to control method tracing. The only one that * is currently defined is {@link #TRACE_COUNT_ALLOCS}. */ + public static void startMethodTracing(String traceFileName, + int bufferSize, int flags) { + startMethodTracing(traceFileName, null, bufferSize, flags); + } + + /** + * Like startMethodTracing(String, int, int), but taking an already-opened + * FileDescriptor in which the trace is written. The file name is also + * supplied simply for logging. Makes a dup of the file descriptor. + * + * Not exposed in the SDK unless we are really comfortable with supporting + * this and find it would be useful. + * @hide + */ public static native void startMethodTracing(String traceFileName, - int bufferSize, int flags); + FileDescriptor fd, int bufferSize, int flags); /** * Determine whether method tracing is currently active. diff --git a/vm/Profile.c b/vm/Profile.c index 8c731f999..8e19b3459 100644 --- a/vm/Profile.c +++ b/vm/Profile.c @@ -320,12 +320,14 @@ static void dumpMethodList(FILE* fp) } /* - * Start method tracing. This opens the file and allocates the buffer. + * Start method tracing. This opens the file (if an already open fd has not + * been supplied) and allocates the buffer. * If any of these fail, we throw an exception and return. * * Method tracing is global to the VM. */ -void dvmMethodTraceStart(const char* traceFileName, int bufferSize, int flags) +void dvmMethodTraceStart(const char* traceFileName, int traceFd, int bufferSize, + int flags) { MethodTraceState* state = &gDvm.methodTrace; @@ -351,7 +353,11 @@ void dvmMethodTraceStart(const char* traceFileName, int bufferSize, int flags) dvmThrowException("Ljava/lang/InternalError;", "buffer alloc failed"); goto fail; } - state->traceFile = fopen(traceFileName, "w"); + if (traceFd < 0) { + state->traceFile = fopen(traceFileName, "w"); + } else { + state->traceFile = fdopen(traceFd, "w"); + } if (state->traceFile == NULL) { LOGE("Unable to open trace file '%s': %s\n", traceFileName, strerror(errno)); diff --git a/vm/Profile.h b/vm/Profile.h index cdaf02767..d5dbea280 100644 --- a/vm/Profile.h +++ b/vm/Profile.h @@ -96,7 +96,8 @@ typedef struct AllocProfState { /* * Start/stop method tracing. */ -void dvmMethodTraceStart(const char* traceFileName, int bufferSize, int flags); +void dvmMethodTraceStart(const char* traceFileName, int traceFd, int bufferSize, + int flags); bool dvmIsMethodTraceActive(void); void dvmMethodTraceStop(void); diff --git a/vm/native/dalvik_system_VMDebug.c b/vm/native/dalvik_system_VMDebug.c index ec6d92ed0..bf7ce6192 100644 --- a/vm/native/dalvik_system_VMDebug.c +++ b/vm/native/dalvik_system_VMDebug.c @@ -209,7 +209,7 @@ static void Dalvik_dalvik_system_VMDebug_resetAllocCount(const u4* args, } /* - * static void startMethodTracing(String traceFileName, + * static void startMethodTracing(String traceFileName, java.io.FileDescriptor, * int bufferSize, int flags) * * Start method trace profiling. @@ -219,8 +219,9 @@ static void Dalvik_dalvik_system_VMDebug_startMethodTracing(const u4* args, { #ifdef WITH_PROFILER StringObject* traceFileStr = (StringObject*) args[0]; - int bufferSize = args[1]; - int flags = args[2]; + DataObject* traceFd = (DataObject*) args[1]; + int bufferSize = args[2]; + int flags = args[3]; char* traceFileName; if (bufferSize == 0) { @@ -229,13 +230,24 @@ static void Dalvik_dalvik_system_VMDebug_startMethodTracing(const u4* args, } if (traceFileStr == NULL || bufferSize < 1024) { - dvmThrowException("Ljava/lang/InvalidArgument;", NULL); + dvmThrowException("Ljava/lang/IllegalArgumentException;", NULL); RETURN_VOID(); } traceFileName = dvmCreateCstrFromString(traceFileStr); - dvmMethodTraceStart(traceFileName, bufferSize, flags); + int fd = -1; + if (traceFd != NULL) { + InstField* field = dvmFindInstanceField(traceFd->obj.clazz, "descriptor", "I"); + if (field == NULL) { + dvmThrowException("Ljava/lang/NoSuchFieldException;", + "No FileDescriptor.descriptor field"); + RETURN_VOID(); + } + fd = dup(dvmGetFieldInt(&traceFd->obj, field->byteOffset)); + } + + dvmMethodTraceStart(traceFileName, fd, bufferSize, flags); free(traceFileName); #else // throw exception? @@ -585,7 +597,7 @@ const DalvikNativeMethod dvm_dalvik_system_VMDebug[] = { Dalvik_dalvik_system_VMDebug_startAllocCounting }, { "stopAllocCounting", "()V", Dalvik_dalvik_system_VMDebug_stopAllocCounting }, - { "startMethodTracing", "(Ljava/lang/String;II)V", + { "startMethodTracing", "(Ljava/lang/String;Ljava/io/FileDescriptor;II)V", Dalvik_dalvik_system_VMDebug_startMethodTracing }, { "isMethodTracingActive", "()Z", Dalvik_dalvik_system_VMDebug_isMethodTracingActive }, -- 2.11.0