How to properly write a SIGPROF handler that invokes AsyncGetCallTrace?
I am writing a short and simple profiler (in C), which is intended to print out stack traces for threads in various Java clients at regular intervals. I have to use the undocumented function AsyncGetCallTrace
instead of GetStackTrace
to minimize intrusion and allow for stack traces regardless of thread state. The source code for the function can be found here: http://download.java.net/openjdk/jdk6/promoted/b20/openjdk-6-src-b20-21_jun_2010.tar.gz
in hotspot/src/share/vm/prims/forte.cpp
. I found some man pages documenting JVMTI, signal handling, and timing, as well as a blog with details on how to set up the AsyncGetCallTrace
call: http://jeremymanson.blogspot.com/2007/05/profiling-with-jvmtijvmpi-sigprof-and.html
What this blog is missing is the code to actually invoke the function within the signal handler (the author assumes the reader can do this on his/her own). I am asking for help in doing exactly this. I am not sure how and where to create the struct ASGCT_CallTrace
(and the internal struct ASGCT_CallFrame
), as defined in the aforementioned file forte.cpp
. The struct ASGCT_CallTrace
is one of the parameters passed to AsyncGetCallTrace
, so I do need to create it, but I don't know how to obtain the correct values for its fields: JNIEnv *env_id
, jint num_frames
, and JVMPI_CallFrame *frames
. Furthermore, I do not know what the third parameter passed to AsyncGetCallTrace (void* ucontext)
is supposed to be?
The above problem is the main one I am having. However, other issues I am faced with include:
SIGPROF
doesn't seem to be raised by the timer exactly at the specified intervals, but rather a bit less frequently. That is, if I set the timer to send aSIGPROF
every second (1 sec, 0 usec), then in a 5 second run, I am getting fewer than 5SIGPROF
handler outputs (usually 1-3)SIGPROF
handler outputs do not appear at all during a 开发者_运维技巧Thread.sleep
in the Java code. So, if aSIGPROF
is to be sent every second, and I haveThread.sleep(5000);
, I will not get any handler outputs during the execution of that code.
Any help would be appreciated. Additional details (as well as parts of code and sample outputs) will be posted upon request.
I finally got a positive result, but since little discussion was spawned here, my own answer will be brief.
The ASGCT_CallTrace structure (and the underlying ASGCT_CallFrame array) can simply be declared in the signal handler, thus existing only the stack: ASGCT_CallTrace trace; JNIEnv *env; global_VM_pointer->AttachCurrentThread((void **) &env, NULL); trace.env_id = env; trace.num_frames = 0; ASGCT_CallFrame storage[25]; trace.frames = storage;
The following gets the uContext: ucontext_t uContext; getcontext(&uContext);
And then the call is just: AsyncGetCallTrace(&trace, 25, &uContext);
I am sure there are some other nuances that I had to take care of in the process, but I did not really document them. I am not sure I can disclose the full current code I have, which successfully asynchronously requests for and obtains stack traces of any java program at fixed intervals. But if someone is interested in or stuck on the same problem, I am now able to help (I think).
On the other two issues: [1] If a thread is sleeping and a SIGPROF is generated, the thread handles that signal only after waking up. This is normal, since it is the thread's job to handle the signal. [2] The timer imperfections do not seem to appear anymore. Perhaps I mis-measured.
精彩评论