static void
genericHandler(JNIEnv *env, EventInfo *evinfo,
               HandlerNode *node,
               struct bag *eventBag)
{
    eventHelper_recordEvent(evinfo, node->handlerID, node->suspendPolicy,
                            eventBag);
}
static void 
handleClassPrepare(JNIEnv *env, JVMDI_Event *event,
                   HandlerNode *node,
                   struct bag *eventBag)
{
    jthread thread = event->u.class_event.thread;
    jclass clazz = event->u.class_event.clazz;

    /* We try hard to avoid class loads/prepares in debugger
     * threads, but it is still possible for them to happen (most
     * likely for exceptions that are thrown within JNI
     * methods). If such an event occurs, we must report it, but
     * we cannot suspend the debugger thread.
     * 
     * 1) We report the thread as NULL because we don't want the
     *    application to get hold of a debugger thread object. 
     * 2) We try to do the right thing wrt to suspending
     *    threads without suspending debugger threads. If the
     *    requested suspend policy is NONE, there's no problem. If
     *    the requested policy is ALL, we can just suspend all
     *    application threads without producing any surprising
     *    results by leaving the debugger thread running. However,
     *    if the requested policy is EVENT_THREAD, we are forced
     *    to do something different than requested. The most
     *    useful behavior is to suspend all application threads
     *    (just as if the policy was ALL). This allows the
     *    application to operate on the class before it gets into
     *    circulation and so it is preferable to the other
     *    alternative of suspending no threads.  
     */
    if (threadControl_isDebugThread(thread)) { 
        event->u.class_event.thread = NULL;
        if (node->suspendPolicy == JDWP_SuspendPolicy_EVENT_THREAD) {
            node->suspendPolicy = JDWP_SuspendPolicy_ALL;
        }
    }
    eventHelper_recordEvent(event, node->handlerID, 
                            node->suspendPolicy, eventBag);
}
Esempio n. 3
0
/*
 * Initialize debugger back end modules
 */
static void
initialize(JNIEnv *env, jthread thread, EventIndex triggering_ei)
{
    jvmtiError error;
    EnumerateArg arg;
    jbyte suspendPolicy;

    LOG_MISC(("Begin initialize()"));
    currentSessionID = 0;
    initComplete = JNI_FALSE;

    if ( gdata->vmDead ) {
        EXIT_ERROR(AGENT_ERROR_INTERNAL,"VM dead at initialize() time");
    }

    /* Turn off the initial JVMTI event notifications */
    error = set_event_notification(JVMTI_DISABLE, EI_EXCEPTION);
    if (error != JVMTI_ERROR_NONE) {
        EXIT_ERROR(error, "unable to disable JVMTI event notification");
    }
    error = set_event_notification(JVMTI_DISABLE, EI_VM_INIT);
    if (error != JVMTI_ERROR_NONE) {
        EXIT_ERROR(error, "unable to disable JVMTI event notification");
    }
    error = set_event_notification(JVMTI_DISABLE, EI_VM_DEATH);
    if (error != JVMTI_ERROR_NONE) {
        EXIT_ERROR(error, "unable to disable JVMTI event notification");
    }

    /* Remove initial event callbacks */
    (void)memset(&(gdata->callbacks),0,sizeof(gdata->callbacks));
    error = JVMTI_FUNC_PTR(gdata->jvmti,SetEventCallbacks)
            (gdata->jvmti, &(gdata->callbacks), sizeof(gdata->callbacks));
    if (error != JVMTI_ERROR_NONE) {
        EXIT_ERROR(error, "unable to clear JVMTI callbacks");
    }

    commonRef_initialize();
    util_initialize(env);
    threadControl_initialize();
    stepControl_initialize();
    invoker_initialize();
    debugDispatch_initialize();
    classTrack_initialize(env);
    debugLoop_initialize();

    initMonitor = debugMonitorCreate("JDWP Initialization Monitor");


    /*
     * Initialize transports
     */
    arg.isServer = isServer;
    arg.error = JDWP_ERROR(NONE);
    arg.startCount = 0;

    transport_initialize();
    (void)bagEnumerateOver(transports, startTransport, &arg);

    /*
     * Exit with an error only if
     * 1) none of the transports was successfully started, and
     * 2) the application has not yet started running
     */
    if ((arg.error != JDWP_ERROR(NONE)) &&
            (arg.startCount == 0) &&
            initOnStartup) {
        EXIT_ERROR(map2jvmtiError(arg.error), "No transports initialized");
    }

    eventHandler_initialize(currentSessionID);

    signalInitComplete();

    transport_waitForConnection();

    suspendPolicy = suspendOnInit ? JDWP_SUSPEND_POLICY(ALL)
                    : JDWP_SUSPEND_POLICY(NONE);
    if (triggering_ei == EI_VM_INIT) {
        LOG_MISC(("triggering_ei == EI_VM_INIT"));
        eventHelper_reportVMInit(env, currentSessionID, thread, suspendPolicy);
    } else {
        /*
         * TO DO: Kludgy way of getting the triggering event to the
         * just-attached debugger. It would be nice to make this a little
         * cleaner. There is also a race condition where other events
         * can get in the queue (from other not-yet-suspended threads)
         * before this one does. (Also need to handle allocation error below?)
         */
        EventInfo info;
        struct bag *initEventBag;
        LOG_MISC(("triggering_ei != EI_VM_INIT"));
        initEventBag = eventHelper_createEventBag();
        (void)memset(&info,0,sizeof(info));
        info.ei = triggering_ei;
        eventHelper_recordEvent(&info, 0, suspendPolicy, initEventBag);
        (void)eventHelper_reportEvents(currentSessionID, initEventBag);
        bagDestroyBag(initEventBag);
    }

    if ( gdata->vmDead ) {
        EXIT_ERROR(AGENT_ERROR_INTERNAL,"VM dead before initialize() completes");
    }
    LOG_MISC(("End initialize()"));
}