In there, the java agent attaches to the SIGQUIT signal. I'd like to avoid that, because that is the same signal that the JVM uses in order to write a thread dump to stdout. I want to avoid that duplicity.
Just remove the following snippet from your code
/* Set callbacks and enable event notifications */
memset(&callbacks, 0, sizeof(callbacks));
callbacks.DataDumpRequest = &dumpThreadInfo;
err = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, sizeof(callbacks));
CHECK_JVMTI_ERROR(jvmti, err);
err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,JVMTI_EVENT_DATA_DUMP_REQUEST, NULL);
CHECK_JVMTI_ERROR(jvmti, err);
I'd like to either attach to a different signal
Here is the paper, that is a bit old, but the information should be still relevant.
Just a sample of how to do a signal handling
import sun.misc.Signal;
import sun.misc.SignalHandler;
public class ThreadDumpSignalHandler implements SignalHandler {
private volatile SignalHandler old;
private ThreadDumpSignalHandler() {
}
public static void register(String sigName) {
ThreadDumpSignalHandler h = new ThreadDumpSignalHandler();
h.old = Signal.handle(new Signal(sigName), h)
}
public void handle(Signal sig) {
threadDump();
if(old != null && old != SIG_DFL && old != SIG_IGN) {
old.handle(sig);
}
}
// call your own threadDump native method.
// note that in the implementation of this method you are able to access jvmtiEnv from *gdata (see below)
private native void threadDump();
}
ThreadDumpSignalHandler.register("INT");
Of cause you can write completely native signal handler (please note that I haven't tested it, this is just an idea that should work)
static sighandler_t old_handler;
static void thread_dump_handler(int signum) {
if(gdata && gdata->jvmti) {
... get thread dump
}
if(old_handler) {
old_handler(signum);
}
}
JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm, char *options, void *reserved) {
old_handler = signal(SIGINT, thread_dump_handler);
...
}
or find a way for the agent to generate a thread dump periodically.
In your sample there is global *gdata
typedef struct {
/* JVMTI Environment */
jvmtiEnv *jvmti;
jboolean vm_is_started;
/* Data access Lock */
jrawMonitorID lock;
} GlobalAgentData;
static GlobalAgentData *gdata;
... so, just obtain jvmtiEnv from there at any time you want (timer callbacks, etc.)
GetStackTrace
directly. Is there a reason you can't do that? – Unlucky