1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-08-05 23:35:48 +02:00

Bug 571161 - MIBreakpointsSynchronizer is broken in certain scenarios

- Added null check to prevent NPE.
- Fixed the collector used in doTargetBreakpointsSynchronized method.

Change-Id: I1ea48b9231882923fe364321e42d0202a0924bf3
Signed-off-by: Umair Sair <umair_sair@hotmail.com>
This commit is contained in:
Umair Sair 2021-02-12 17:57:30 +05:00 committed by Jonah Graham
parent 7760ce2eb7
commit 321100a2a7

View file

@ -15,6 +15,7 @@
* Marc Khouzam (Ericsson) - Support for dynamic printf (Bug 400628) * Marc Khouzam (Ericsson) - Support for dynamic printf (Bug 400628)
* Jonah Graham (Kichwa Coders) - Bug 317173 - cleanup warnings * Jonah Graham (Kichwa Coders) - Bug 317173 - cleanup warnings
* Jonah Graham (Kichwa Coders) - Bug 530377 - Corruption of state due to fast events from GDB * Jonah Graham (Kichwa Coders) - Bug 530377 - Corruption of state due to fast events from GDB
* Umair Sair (Siemens) - Bug 571161 - MIBreakpointsSynchronizer is broken in certain scenarios
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.dsf.mi.service; package org.eclipse.cdt.dsf.mi.service;
@ -24,6 +25,7 @@ import java.math.BigInteger;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.Deque; import java.util.Deque;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
@ -384,29 +386,35 @@ public class MIBreakpointsSynchronizer extends AbstractDsfService
.getBPToPlatformMaps(); .getBPToPlatformMaps();
Stream<IBreakpointDMContext> breakpointsKnownToManager = bpToPlatformMaps.entrySet().stream() Stream<IBreakpointDMContext> breakpointsKnownToManager = bpToPlatformMaps.entrySet().stream()
.flatMap(m -> m.getValue().keySet().stream()); .flatMap(m -> m.getValue().keySet().stream());
Collector<MIBreakpointDMContext, ?, Map<IBreakpointsTargetDMContext, String>> collector = Collectors.toMap( Collector<MIBreakpointDMContext, ?, Map<IBreakpointsTargetDMContext, Set<String>>> collector = Collectors.toMap(
(MIBreakpointDMContext dmc) -> DMContexts.getAncestorOfType(dmc, IBreakpointsTargetDMContext.class), (MIBreakpointDMContext dmc) -> DMContexts.getAncestorOfType(dmc, IBreakpointsTargetDMContext.class),
(MIBreakpointDMContext dmc) -> dmc.getReference()); (MIBreakpointDMContext dmc) -> new HashSet<>(Collections.singleton(dmc.getReference())),
Map<IBreakpointsTargetDMContext, String> numbersKnownToManager = breakpointsKnownToManager (a, b) -> Stream.concat(a.stream(), b.stream()).collect(Collectors.toCollection(HashSet::new)));
Map<IBreakpointsTargetDMContext, Set<String>> numbersKnownToManager = breakpointsKnownToManager
.filter(MIBreakpointDMContext.class::isInstance).map(MIBreakpointDMContext.class::cast) .filter(MIBreakpointDMContext.class::isInstance).map(MIBreakpointDMContext.class::cast)
.collect(collector); .collect(collector);
for (MIBreakpoint miBpt : data.getMIBreakpoints()) { for (MIBreakpoint miBpt : data.getMIBreakpoints()) {
String number = miBpt.getNumber(); String number = miBpt.getNumber();
if (numbersKnownToManager.values().remove(number)) {
boolean found = false;
for (Set<String> bpNumbers : numbersKnownToManager.values())
if (bpNumbers.remove(number))
found = true;
BreakpointEvent event = new BreakpointEvent(); BreakpointEvent event = new BreakpointEvent();
if (found)
event.modified = miBpt; event.modified = miBpt;
fBreakpointEvents.addFirst(event); else
} else {
BreakpointEvent event = new BreakpointEvent();
event.created = miBpt; event.created = miBpt;
fBreakpointEvents.addFirst(event); fBreakpointEvents.addFirst(event);
} }
}
for (Entry<IBreakpointsTargetDMContext, String> entry : numbersKnownToManager.entrySet()) { for (Entry<IBreakpointsTargetDMContext, Set<String>> entry : numbersKnownToManager.entrySet()) {
IBreakpointsTargetDMContext dmc = entry.getKey(); IBreakpointsTargetDMContext dmc = entry.getKey();
String number = entry.getValue(); for (String number : entry.getValue())
if (number != null && !number.isEmpty() && (breakpointsContext == null || breakpointsContext.equals(dmc))) { if (number != null && !number.isEmpty()
&& (breakpointsContext == null || breakpointsContext.equals(dmc))) {
BreakpointEvent event = new BreakpointEvent(); BreakpointEvent event = new BreakpointEvent();
event.deleted = number; event.deleted = number;
fBreakpointEvents.addFirst(event); fBreakpointEvents.addFirst(event);
@ -750,7 +758,9 @@ public class MIBreakpointsSynchronizer extends AbstractDsfService
if (!plBpt.getCondition().equals(miBpt.getCondition())) { if (!plBpt.getCondition().equals(miBpt.getCondition())) {
plBpt.setCondition(miBpt.getCondition()); plBpt.setCondition(miBpt.getCondition());
} }
if (oldData.isPending() != miBpt.isPending()) { // oldData can be null for notifications of breakpoints that are inserted using DSF but
// not with breakpoint service
if (oldData != null && oldData.isPending() != miBpt.isPending()) {
if (miBpt.isPending()) { if (miBpt.isPending()) {
plBpt.decrementInstallCount(); plBpt.decrementInstallCount();
} else { } else {
@ -801,7 +811,10 @@ public class MIBreakpointsSynchronizer extends AbstractDsfService
// } // }
} }
} catch (CoreException e) { } catch (CoreException e) {
if (oldData != null)
contextBreakpoints.put(miBpt.getNumber(), oldData); contextBreakpoints.put(miBpt.getNumber(), oldData);
else
contextBreakpoints.remove(miBpt.getNumber());
GdbPlugin.log(e.getStatus()); GdbPlugin.log(e.getStatus());
} }
} }
@ -1559,7 +1572,7 @@ public class MIBreakpointsSynchronizer extends AbstractDsfService
return; return;
} }
sourceLookup.getSource(srcDmc, debuggerPath, new DataRequestMonitor<Object>(getExecutor(), rm) { sourceLookup.getSource(srcDmc, debuggerPath, new DataRequestMonitor<>(getExecutor(), rm) {
@Override @Override
@ConfinedToDsfExecutor("fExecutor") @ConfinedToDsfExecutor("fExecutor")
protected void handleCompleted() { protected void handleCompleted() {