void (final SuspendContextImpl suspendContext, final LocatableEvent event) { ThreadReference thread = event.thread(); //LOG.assertTrue(thread.isSuspended()); preprocessEvent(suspendContext, thread); //we use schedule to allow processing other events during processing this one //this is especially necessary if a method is breakpoint condition getManagerThread().schedule(new SuspendContextCommandImpl(suspendContext) { @Override public void contextAction(@NotNull SuspendContextImpl suspendContext) { final SuspendManager suspendManager = getSuspendManager(); SuspendContextImpl evaluatingContext = SuspendManagerUtil.getEvaluatingContext(suspendManager, suspendContext.getThread()); final LocatableEventRequestor requestor = (LocatableEventRequestor)RequestManagerImpl.findRequestor(event.request()); if (evaluatingContext != null && !(requestor instanceof InstrumentationTracker.InstrumentationMethodBreakpoint) && !DebuggerSession.enableBreakpointsDuringEvaluation()) { notifySkippedBreakpoints(event, SkippedBreakpointReason.EVALUATION); // is inside evaluation, so ignore any breakpoints suspendManager.voteResume(suspendContext); return; } // Skip breakpoints in other threads during suspend-all stepping. // // Don't try to check breakpoint's condition or evaluate its log expression, // because these evaluations may lead to skipping of more important stepping events, // see IDEA-336282. if (!DebuggerSession.filterBreakpointsDuringSteppingUsingDebuggerEngine()) { ThreadReference filteredThread = getRequestsManager().getFilterThread(); if (filteredThread != null && !Comparing.equal(filteredThread, thread)) { notifySkippedBreakpoints(event, SkippedBreakpointReason.STEPPING); suspendManager.voteResume(suspendContext); return; } } boolean resumePreferred = requestor != null && DebuggerSettings.SUSPEND_NONE.equals(requestor.getSuspendPolicy()); boolean requestHit = false; long startTimeNs = System.nanoTime(); long endTimeNs = 0; try { requestHit = (requestor != null) && requestor.processLocatableEvent(this, event); } catch (final LocatableEventRequestor.EventProcessingException ex) { // stop timer here to prevent reporting dialog opened time endTimeNs = System.nanoTime(); if (LOG.isDebugEnabled()) { LOG.debug(ex.getMessage()); } final boolean[] considerRequestHit = new boolean[]{true}; DebuggerInvocationUtil.invokeAndWait(getProject(), () -> { final String displayName = requestor instanceof Breakpoint ? ((Breakpoint<?>)requestor).getDisplayName() : requestor.getClass().getSimpleName(); final String message = JavaDebuggerBundle.message("error.evaluating.breakpoint.condition.or.action", displayName, ex.getMessage()); considerRequestHit[0] = Messages.showYesNoDialog(getProject(), message, ex.getTitle(), Messages.getQuestionIcon()) == Messages.YES; }, ModalityState.nonModal()); requestHit = considerRequestHit[0]; resumePreferred = !requestHit; } catch (VMDisconnectedException e) { throw e; } catch (Exception e) { // catch everything else here to be able to vote LOG.error(e); } finally { if (endTimeNs == 0) { endTimeNs = System.nanoTime(); } long timeMs = TimeUnit.NANOSECONDS.toMillis(endTimeNs - startTimeNs); if (requestor instanceof Breakpoint<?> breakpoint) { DebuggerStatistics.logBreakpointVisit(breakpoint, timeMs); } if (requestor instanceof OverheadProducer && ((OverheadProducer)requestor).track()) { OverheadTimings.add(DebugProcessEvents.this, (OverheadProducer)requestor, requestHit || requestor instanceof StackCapturingLineBreakpoint ? 1 : 0, timeMs); } } if (requestHit && requestor instanceof Breakpoint) { // if requestor is a breakpoint and this breakpoint was hit, no matter its suspend policy ApplicationManager.getApplication().runReadAction(() -> { XDebugSession session = getSession().getXDebugSession(); if (session != null) { XBreakpoint breakpoint = ((Breakpoint)requestor).getXBreakpoint(); if (breakpoint != null) { ((XDebugSessionImpl)session).processDependencies(breakpoint); } } }); } // special check for smart step into with this breakpoint inside the expressions EventSet eventSet = suspendContext.getEventSet(); if (eventSet != null && eventSet.size() > 1) { List<StepEvent> stepEvents = ContainerUtil.filterIsInstance(eventSet, StepEvent.class); if (!stepEvents.isEmpty()) { resumePreferred = resumePreferred || stepEvents.stream() .map(DebugProcessEvents::getRequestHint) .allMatch(h -> { if (h != null) { Integer depth = h.checkCurrentPosition(suspendContext, event.location()); return depth != null && depth != RequestHint.STOP; } return false; }); } } if (!requestHit || resumePreferred) { suspendManager.voteResume(suspendContext); } else { stopWatchingMethodReturn(); //if (suspendContext.getSuspendPolicy() == EventRequest.SUSPEND_ALL) { // // there could be explicit resume as a result of call to voteSuspend() // // e.g. when breakpoint was considered invalid, in that case the filter will be applied _after_ // // resuming and all breakpoints in other threads will be ignored. // // As resume() implicitly cleares the filter, the filter must be always applied _before_ any resume() action happens // myBreakpointManager.applyThreadFilter(DebugProcessEvents.this, event.thread()); //} suspendManager.voteSuspend(suspendContext); showStatusText(DebugProcessEvents.this, event); } } }); }