1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-09 10:46:02 +02:00

Fix for bug 58711: Breakpoint race condition.

This commit is contained in:
Mikhail Khodjaiants 2004-04-19 22:12:02 +00:00
parent 6b096ee976
commit e2983ad1f8
14 changed files with 633 additions and 239 deletions

View file

@ -1,3 +1,20 @@
2004-04-15 Mikhail Khodjaiants
Fix for bug 58711: Breakpoint race condition.
To avoid race condition all breakpoint marker updates (like increment/decrement the install count,
enable/disable etc.) should be done in the UI thread. At the same time installing breakpoint
at a target should be synchronized with other gdb commands (bug 58711).
A special listener (CBreakpointUpdater) has been added to receive notifications from the event
thread and post marker updates to the UI thread.
* CDebugCorePlugin.java
* ICBreakpointListener.java: new
* ICBreakpoint.java
* CBreakpointManager.java
* CBreakpointNotifier.java: new
* ListenerList.java: new
* CBreakpoint.java
* CDebugTarget.java
* IAsyncExecutor.java: removed
2004-04-19 Mikhail Khodjaiants 2004-04-19 Mikhail Khodjaiants
Display global variable name in the error message when the "Add Globals" action fails. Display global variable name in the error message when the "Add Globals" action fails.
* CDebugModel.java * CDebugModel.java

View file

@ -1,9 +1,13 @@
/* /**********************************************************************
*(c) Copyright QNX Software Systems Ltd. 2002. * Copyright (c) 2004 QNX Software Systems and others.
* All Rights Reserved. * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
* *
*/ * Contributors:
* QNX Software Systems - Initial API and implementation
***********************************************************************/
package org.eclipse.cdt.debug.core; package org.eclipse.cdt.debug.core;
import java.text.MessageFormat; import java.text.MessageFormat;
@ -13,6 +17,7 @@ import java.util.ResourceBundle;
import org.eclipse.cdt.debug.core.sourcelookup.ICSourceLocation; import org.eclipse.cdt.debug.core.sourcelookup.ICSourceLocation;
import org.eclipse.cdt.debug.internal.core.DebugConfiguration; import org.eclipse.cdt.debug.internal.core.DebugConfiguration;
import org.eclipse.cdt.debug.internal.core.ListenerList;
import org.eclipse.cdt.debug.internal.core.SessionManager; import org.eclipse.cdt.debug.internal.core.SessionManager;
import org.eclipse.cdt.debug.internal.core.breakpoints.CBreakpoint; import org.eclipse.cdt.debug.internal.core.breakpoints.CBreakpoint;
import org.eclipse.cdt.debug.internal.core.sourcelookup.SourceUtils; import org.eclipse.cdt.debug.internal.core.sourcelookup.SourceUtils;
@ -32,37 +37,43 @@ import org.eclipse.debug.core.model.IBreakpoint;
import org.eclipse.cdt.debug.core.CDebugCorePlugin; import org.eclipse.cdt.debug.core.CDebugCorePlugin;
/** /**
* The main plugin class to be used in the desktop. * The plugin class for C/C++ debug core.
*/ */
public class CDebugCorePlugin extends Plugin public class CDebugCorePlugin extends Plugin {
{
/** /**
* Status code indicating an unexpected internal error. * Status code indicating an unexpected internal error.
*/ */
public static final int INTERNAL_ERROR = 1000; public static final int INTERNAL_ERROR = 1000;
//The shared instance. /**
* The shared instance.
*/
private static CDebugCorePlugin plugin; private static CDebugCorePlugin plugin;
private static ResourceBundle fgResourceBundle; private static ResourceBundle fgResourceBundle;
private HashMap fDebugConfigurations; private HashMap fDebugConfigurations;
private IAsyncExecutor fAsyncExecutor = null; /**
* Breakpoint listener list.
*/
private ListenerList fBreakpointListeners;
private SessionManager fSessionManager = null; private SessionManager fSessionManager = null;
static { static {
try { try {
fgResourceBundle = ResourceBundle.getBundle( "org.eclipse.cdt.debug.core.CDebugCorePluginResources" ); //$NON-NLS-1$ fgResourceBundle = ResourceBundle.getBundle( "org.eclipse.cdt.debug.core.CDebugCorePluginResources" ); //$NON-NLS-1$
} catch (MissingResourceException x) { }
catch( MissingResourceException x ) {
fgResourceBundle = null; fgResourceBundle = null;
} }
} }
/** /**
* The constructor. * The constructor.
*/ */
public CDebugCorePlugin( IPluginDescriptor descriptor ) public CDebugCorePlugin( IPluginDescriptor descriptor ) {
{
super( descriptor ); super( descriptor );
plugin = this; plugin = this;
} }
@ -72,8 +83,7 @@ public class CDebugCorePlugin extends Plugin
* *
* @return the shared instance * @return the shared instance
*/ */
public static CDebugCorePlugin getDefault() public static CDebugCorePlugin getDefault() {
{
return plugin; return plugin;
} }
@ -82,8 +92,7 @@ public class CDebugCorePlugin extends Plugin
* *
* @return the workspace instance * @return the workspace instance
*/ */
public static IWorkspace getWorkspace() public static IWorkspace getWorkspace() {
{
return ResourcesPlugin.getWorkspace(); return ResourcesPlugin.getWorkspace();
} }
@ -92,10 +101,8 @@ public class CDebugCorePlugin extends Plugin
* *
* @return the unique identifier of this plugin * @return the unique identifier of this plugin
*/ */
public static String getUniqueIdentifier() public static String getUniqueIdentifier() {
{ if ( getDefault() == null ) {
if ( getDefault() == null )
{
// If the default instance is not yet initialized, // If the default instance is not yet initialized,
// return a static identifier. This identifier must // return a static identifier. This identifier must
// match the plugin id defined in plugin.xml // match the plugin id defined in plugin.xml
@ -107,12 +114,15 @@ public class CDebugCorePlugin extends Plugin
public static String getResourceString( String key ) { public static String getResourceString( String key ) {
try { try {
return fgResourceBundle.getString( key ); return fgResourceBundle.getString( key );
} catch (MissingResourceException e) { }
catch( MissingResourceException e ) {
return "!" + key + "!"; //$NON-NLS-1$ //$NON-NLS-2$ return "!" + key + "!"; //$NON-NLS-1$ //$NON-NLS-2$
} catch (NullPointerException e) { }
catch( NullPointerException e ) {
return "#" + key + "#"; //$NON-NLS-1$ //$NON-NLS-2$ return "#" + key + "#"; //$NON-NLS-1$ //$NON-NLS-2$
} }
} }
public static String getFormattedString( String key, String arg ) { public static String getFormattedString( String key, String arg ) {
return MessageFormat.format( getResourceString( key ), new String[]{ arg } ); return MessageFormat.format( getResourceString( key ), new String[]{ arg } );
} }
@ -130,15 +140,12 @@ public class CDebugCorePlugin extends Plugin
* *
* @param t throwable to log * @param t throwable to log
*/ */
public static void log( Throwable t ) public static void log( Throwable t ) {
{
Throwable top = t; Throwable top = t;
if ( t instanceof DebugException ) if ( t instanceof DebugException ) {
{
DebugException de = (DebugException)t; DebugException de = (DebugException)t;
IStatus status = de.getStatus(); IStatus status = de.getStatus();
if ( status.getException() != null ) if ( status.getException() != null ) {
{
top = status.getException(); top = status.getException();
} }
} }
@ -152,8 +159,7 @@ public class CDebugCorePlugin extends Plugin
* *
* @param status status to log * @param status status to log
*/ */
public static void log( IStatus status ) public static void log( IStatus status ) {
{
getDefault().getLog().log( status ); getDefault().getLog().log( status );
} }
@ -162,13 +168,8 @@ public class CDebugCorePlugin extends Plugin
* *
* @param status status to log * @param status status to log
*/ */
public static void log( String message ) public static void log( String message ) {
{ getDefault().getLog().log( new Status( IStatus.ERROR, CDebugModel.getPluginIdentifier(), INTERNAL_ERROR, message, null ) );
getDefault().getLog().log( new Status( IStatus.ERROR,
CDebugModel.getPluginIdentifier(),
INTERNAL_ERROR,
message,
null ) );
} }
private void initializeDebugConfiguration() { private void initializeDebugConfiguration() {
@ -205,9 +206,9 @@ public class CDebugCorePlugin extends Plugin
/* (non-Javadoc) /* (non-Javadoc)
* @see org.eclipse.core.runtime.Plugin#shutdown() * @see org.eclipse.core.runtime.Plugin#shutdown()
*/ */
public void shutdown() throws CoreException public void shutdown() throws CoreException {
{
setSessionManager( null ); setSessionManager( null );
disposeBreakpointListenersList();
resetBreakpointsInstallCount(); resetBreakpointsInstallCount();
super.shutdown(); super.shutdown();
} }
@ -215,63 +216,79 @@ public class CDebugCorePlugin extends Plugin
/* (non-Javadoc) /* (non-Javadoc)
* @see org.eclipse.core.runtime.Plugin#startup() * @see org.eclipse.core.runtime.Plugin#startup()
*/ */
public void startup() throws CoreException public void startup() throws CoreException {
{
super.startup(); super.startup();
createBreakpointListenersList();
resetBreakpointsInstallCount(); resetBreakpointsInstallCount();
setSessionManager( new SessionManager() ); setSessionManager( new SessionManager() );
} }
protected void resetBreakpointsInstallCount() protected void resetBreakpointsInstallCount() {
{
IBreakpointManager bm = DebugPlugin.getDefault().getBreakpointManager(); IBreakpointManager bm = DebugPlugin.getDefault().getBreakpointManager();
IBreakpoint[] breakpoints = bm.getBreakpoints( getUniqueIdentifier() ); IBreakpoint[] breakpoints = bm.getBreakpoints( getUniqueIdentifier() );
for ( int i = 0; i < breakpoints.length; ++i ) for( int i = 0; i < breakpoints.length; ++i ) {
{ if ( breakpoints[i] instanceof CBreakpoint ) {
if ( breakpoints[i] instanceof CBreakpoint ) try {
{
try
{
((CBreakpoint)breakpoints[i]).resetInstallCount(); ((CBreakpoint)breakpoints[i]).resetInstallCount();
} }
catch( CoreException e ) catch( CoreException e ) {
{
log( e.getStatus() ); log( e.getStatus() );
} }
} }
} }
} }
public void setAsyncExecutor( IAsyncExecutor executor ) protected SessionManager getSessionManager() {
{
fAsyncExecutor = executor;
}
public void asyncExec( Runnable runnable )
{
if ( fAsyncExecutor != null )
fAsyncExecutor.asyncExec( runnable );
}
protected SessionManager getSessionManager()
{
return fSessionManager; return fSessionManager;
} }
protected void setSessionManager( SessionManager sm ) protected void setSessionManager( SessionManager sm ) {
{
if ( fSessionManager != null ) if ( fSessionManager != null )
fSessionManager.dispose(); fSessionManager.dispose();
fSessionManager = sm; fSessionManager = sm;
} }
public void saveCommonSourceLocations( ICSourceLocation[] locations ) public void saveCommonSourceLocations( ICSourceLocation[] locations ) {
{
CDebugCorePlugin.getDefault().getPluginPreferences().setValue( ICDebugConstants.PREF_SOURCE_LOCATIONS, SourceUtils.getCommonSourceLocationsMemento( locations ) ); CDebugCorePlugin.getDefault().getPluginPreferences().setValue( ICDebugConstants.PREF_SOURCE_LOCATIONS, SourceUtils.getCommonSourceLocationsMemento( locations ) );
} }
public ICSourceLocation[] getCommonSourceLocations() public ICSourceLocation[] getCommonSourceLocations() {
{
return SourceUtils.getCommonSourceLocationsFromMemento( CDebugCorePlugin.getDefault().getPluginPreferences().getString( ICDebugConstants.PREF_SOURCE_LOCATIONS ) ); return SourceUtils.getCommonSourceLocationsFromMemento( CDebugCorePlugin.getDefault().getPluginPreferences().getString( ICDebugConstants.PREF_SOURCE_LOCATIONS ) );
} }
/**
* Adds the given breakpoint listener to the debug model.
*
* @param listener breakpoint listener
*/
public void addCBreakpointListener( ICBreakpointListener listener ) {
fBreakpointListeners.add( listener );
}
/**
* Removes the given breakpoint listener from the debug model.
*
* @param listener breakpoint listener
*/
public void removeCBreakpointListener( ICBreakpointListener listener ) {
fBreakpointListeners.remove( listener );
}
/**
* Returns the list of breakpoint listeners registered with this plugin.
*
* @return the list of breakpoint listeners registered with this plugin
*/
public Object[] getCBreakpointListeners() {
return fBreakpointListeners.getListeners();
}
private void createBreakpointListenersList() {
fBreakpointListeners = new ListenerList( 1 );
}
private void disposeBreakpointListenersList() {
fBreakpointListeners.removeAll();
fBreakpointListeners = null;
}
} }

View file

@ -1,16 +0,0 @@
/*
*(c) Copyright QNX Software Systems Ltd. 2002.
* All Rights Reserved.
*
*/
package org.eclipse.cdt.debug.core;
/**
* Enter type comment.
*
* @since: Jan 27, 2003
*/
public interface IAsyncExecutor
{
void asyncExec( Runnable runnable );
}

View file

@ -0,0 +1,57 @@
/*
* Created on Apr 14, 2004
*
* To change the template for this generated file go to
* Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
*/
package org.eclipse.cdt.debug.core;
import java.util.Map;
import org.eclipse.debug.core.model.IBreakpoint;
import org.eclipse.debug.core.model.IDebugTarget;
/**
* Provides event and error notification for C/C++ breakpoints.
* Listeners register with the <code>CDebugModel</code>.
*/
public interface ICBreakpointListener
{
/**
* Notification that the given breakpoint is about to be installed in
* the specified target. Returns whether the installation should proceed.
* If any registered listener returns <code>false</code> the breakpoint is
* not installed in the given target.
*
* @param target debug target
* @param breakpoint breakpoint being installed
* @return whether the the breakpoint should be installed in the given target
*/
public boolean installingBreakpoint( IDebugTarget target, IBreakpoint breakpoint );
/**
* Notification that the given breakpoint has been installed in the specified target.
*
* @param target debug target
* @param breakpoint breakpoint being installed
*/
public void breakpointInstalled( IDebugTarget target, IBreakpoint breakpoint );
/**
* Notification that the attributes of the given breakpoint have been changed
* from the specified target.
*
* @param target debug target
* @param breakpoint breakpoint
* @param attributes a map of changed attributes
*/
public void breakpointChanged( IDebugTarget target, IBreakpoint breakpoint, Map attributes );
/**
* Notification that the given breakpoint has been removed from the specified target.
*
* @param target debug target
* @param breakpoint breakpoint being removed
*/
public void breakpointRemoved( IDebugTarget target, IBreakpoint breakpoint );
}

View file

@ -151,4 +151,30 @@ public interface ICBreakpoint extends IBreakpoint {
* underlying marker * underlying marker
*/ */
public void setSourceHandle( String sourceHandle ) throws CoreException; public void setSourceHandle( String sourceHandle ) throws CoreException;
/**
* Increments the install count of this breakpoint
*
* @return the new install count value
* @throws CoreException if unable to access the property
* on this breakpoint's underlying marker
*/
public int incrementInstallCount() throws CoreException;
/**
* Decrements the install count of this breakpoint.
*
* @return the new install caount value
* @throws CoreException if unable to access the property
* on this breakpoint's underlying marker
*/
public int decrementInstallCount() throws CoreException;
/**
* Resets the install count of this breakpoint
*
* @throws CoreException if unable to access the property
* on this breakpoint's underlying marker
*/
public void resetInstallCount() throws CoreException;
} }

View file

@ -11,6 +11,7 @@
package org.eclipse.cdt.debug.internal.core; package org.eclipse.cdt.debug.internal.core;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map;
import java.util.Set; import java.util.Set;
import org.eclipse.cdt.debug.core.CDIDebugModel; import org.eclipse.cdt.debug.core.CDIDebugModel;
@ -87,7 +88,7 @@ public class CBreakpointManager implements ICDIEventListener, IAdaptable {
return (ICBreakpoint)fCDIBreakpoints.get( cdiBreakpoint ); return (ICBreakpoint)fCDIBreakpoints.get( cdiBreakpoint );
} }
protected void removeCBreakpoint( ICBreakpoint breakpoint ) { protected synchronized void removeCBreakpoint( ICBreakpoint breakpoint ) {
if ( breakpoint != null ) { if ( breakpoint != null ) {
ICDIBreakpoint cdiBreakpoint = (ICDIBreakpoint)fCBreakpoints.remove( breakpoint ); ICDIBreakpoint cdiBreakpoint = (ICDIBreakpoint)fCBreakpoints.remove( breakpoint );
if ( cdiBreakpoint != null ) if ( cdiBreakpoint != null )
@ -95,7 +96,7 @@ public class CBreakpointManager implements ICDIEventListener, IAdaptable {
} }
} }
protected void removeCDIBreakpoint( ICBreakpoint breakpoin, ICDIBreakpoint cdiBreakpoint ) { protected synchronized void removeCDIBreakpoint( ICDIBreakpoint cdiBreakpoint ) {
if ( cdiBreakpoint != null ) { if ( cdiBreakpoint != null ) {
ICBreakpoint breakpoint = (ICBreakpoint)fCDIBreakpoints.remove( cdiBreakpoint ); ICBreakpoint breakpoint = (ICBreakpoint)fCDIBreakpoints.remove( cdiBreakpoint );
if ( breakpoint != null ) if ( breakpoint != null )
@ -257,19 +258,9 @@ public class CBreakpointManager implements ICDIEventListener, IAdaptable {
return 0; return 0;
} }
public void setBreakpoint( final ICBreakpoint breakpoint ) throws DebugException { public void setBreakpoint( ICBreakpoint breakpoint ) throws DebugException {
Runnable runnable = new Runnable() {
public void run() {
try {
doSetBreakpoint( breakpoint ); doSetBreakpoint( breakpoint );
} }
catch( DebugException e ) {
}
}
};
CDebugCorePlugin.getDefault().asyncExec( runnable );
}
protected void doSetBreakpoint( ICBreakpoint breakpoint ) throws DebugException { protected void doSetBreakpoint( ICBreakpoint breakpoint ) throws DebugException {
try { try {
@ -302,17 +293,8 @@ public class CBreakpointManager implements ICDIEventListener, IAdaptable {
} }
public void removeBreakpoint( final ICBreakpoint breakpoint ) throws DebugException { public void removeBreakpoint( final ICBreakpoint breakpoint ) throws DebugException {
Runnable runnable = new Runnable() {
public void run() {
try {
doRemoveBreakpoint( breakpoint ); doRemoveBreakpoint( breakpoint );
} }
catch( DebugException e ) {
}
}
};
CDebugCorePlugin.getDefault().asyncExec( runnable );
}
protected void doRemoveBreakpoint( ICBreakpoint breakpoint ) throws DebugException { protected void doRemoveBreakpoint( ICBreakpoint breakpoint ) throws DebugException {
ICDIBreakpoint cdiBreakpoint = getBreakpointMap().getCDIBreakpoint( breakpoint ); ICDIBreakpoint cdiBreakpoint = getBreakpointMap().getCDIBreakpoint( breakpoint );
@ -328,18 +310,8 @@ public class CBreakpointManager implements ICDIEventListener, IAdaptable {
} }
public void changeBreakpointProperties( final ICBreakpoint breakpoint, final IMarkerDelta delta ) throws DebugException { public void changeBreakpointProperties( final ICBreakpoint breakpoint, final IMarkerDelta delta ) throws DebugException {
Runnable runnable = new Runnable() {
public void run() {
try {
doChangeBreakpointProperties( breakpoint, delta ); doChangeBreakpointProperties( breakpoint, delta );
} }
catch( DebugException e ) {
}
}
};
CDebugCorePlugin.getDefault().asyncExec( runnable );
}
protected void doChangeBreakpointProperties( ICBreakpoint breakpoint, IMarkerDelta delta ) throws DebugException { protected void doChangeBreakpointProperties( ICBreakpoint breakpoint, IMarkerDelta delta ) throws DebugException {
ICDIBreakpoint cdiBreakpoint = getBreakpointMap().getCDIBreakpoint( breakpoint ); ICDIBreakpoint cdiBreakpoint = getBreakpointMap().getCDIBreakpoint( breakpoint );
@ -370,17 +342,11 @@ public class CBreakpointManager implements ICDIEventListener, IAdaptable {
} }
private void handleBreakpointCreatedEvent( final ICDIBreakpoint cdiBreakpoint ) { private void handleBreakpointCreatedEvent( final ICDIBreakpoint cdiBreakpoint ) {
Runnable runnable = new Runnable() {
public void run() {
if ( cdiBreakpoint instanceof ICDILocationBreakpoint ) if ( cdiBreakpoint instanceof ICDILocationBreakpoint )
doHandleLocationBreakpointCreatedEvent( (ICDILocationBreakpoint)cdiBreakpoint ); doHandleLocationBreakpointCreatedEvent( (ICDILocationBreakpoint)cdiBreakpoint );
else if ( cdiBreakpoint instanceof ICDIWatchpoint ) else if ( cdiBreakpoint instanceof ICDIWatchpoint )
doHandleWatchpointCreatedEvent( (ICDIWatchpoint)cdiBreakpoint ); doHandleWatchpointCreatedEvent( (ICDIWatchpoint)cdiBreakpoint );
} }
};
CDebugCorePlugin.getDefault().asyncExec( runnable );
}
protected void doHandleLocationBreakpointCreatedEvent( ICDILocationBreakpoint cdiBreakpoint ) { protected void doHandleLocationBreakpointCreatedEvent( ICDILocationBreakpoint cdiBreakpoint ) {
if ( cdiBreakpoint.isTemporary() ) if ( cdiBreakpoint.isTemporary() )
@ -410,12 +376,7 @@ public class CBreakpointManager implements ICDIEventListener, IAdaptable {
} }
} }
if ( breakpoint != null ) { if ( breakpoint != null ) {
try { getBreakpointNotifier().breakpointInstalled( getDebugTarget(), breakpoint );
((CBreakpoint)breakpoint).incrementInstallCount();
}
catch( CoreException e ) {
CDebugCorePlugin.log( e.getStatus() );
}
} }
} }
@ -431,60 +392,38 @@ public class CBreakpointManager implements ICDIEventListener, IAdaptable {
} }
} }
if ( breakpoint != null ) { if ( breakpoint != null ) {
try { getBreakpointNotifier().breakpointInstalled( getDebugTarget(), breakpoint );
((CBreakpoint)breakpoint).incrementInstallCount();
}
catch( CoreException e ) {
CDebugCorePlugin.log( e.getStatus() );
}
} }
} }
private void handleBreakpointDestroyedEvent( final ICDIBreakpoint cdiBreakpoint ) { private void handleBreakpointDestroyedEvent( final ICDIBreakpoint cdiBreakpoint ) {
Runnable runnable = new Runnable() {
public void run() {
doHandleBreakpointDestroyedEvent( cdiBreakpoint );
}
};
CDebugCorePlugin.getDefault().asyncExec( runnable );
}
protected void doHandleBreakpointDestroyedEvent( ICDIBreakpoint cdiBreakpoint ) {
ICBreakpoint breakpoint = getBreakpointMap().getCBreakpoint( cdiBreakpoint ); ICBreakpoint breakpoint = getBreakpointMap().getCBreakpoint( cdiBreakpoint );
getBreakpointMap().removeCDIBreakpoint( cdiBreakpoint );
if ( breakpoint != null ) { if ( breakpoint != null ) {
getBreakpointMap().removeCDIBreakpoint( breakpoint, cdiBreakpoint ); getBreakpointNotifier().breakpointRemoved( getDebugTarget(), breakpoint );
try {
((CBreakpoint)breakpoint).decrementInstallCount();
}
catch( CoreException e ) {
CDebugCorePlugin.log( e.getStatus() );
}
} }
} }
private void handleBreakpointChangedEvent( final ICDIBreakpoint cdiBreakpoint ) { private void handleBreakpointChangedEvent( final ICDIBreakpoint cdiBreakpoint ) {
Runnable runnable = new Runnable() {
public void run() {
doHandleBreakpointChangedEvent( cdiBreakpoint );
}
};
CDebugCorePlugin.getDefault().asyncExec( runnable );
}
protected void doHandleBreakpointChangedEvent( ICDIBreakpoint cdiBreakpoint ) {
ICBreakpoint breakpoint = getBreakpointMap().getCBreakpoint( cdiBreakpoint ); ICBreakpoint breakpoint = getBreakpointMap().getCBreakpoint( cdiBreakpoint );
if ( breakpoint != null ) { if ( breakpoint != null ) {
Map map = new HashMap( 3 );
try { try {
breakpoint.setEnabled( cdiBreakpoint.isEnabled() ); map.put( IBreakpoint.ENABLED, new Boolean( cdiBreakpoint.isEnabled() ) );
breakpoint.setIgnoreCount( cdiBreakpoint.getCondition().getIgnoreCount() );
breakpoint.setCondition( cdiBreakpoint.getCondition().getExpression() );
} }
catch( CDIException e ) { catch( CDIException e ) {
} }
catch( CoreException e ) { try {
map.put( ICBreakpoint.IGNORE_COUNT, new Integer( cdiBreakpoint.getCondition().getIgnoreCount() ) );
} }
catch( CDIException e ) {
}
try {
map.put( ICBreakpoint.CONDITION, cdiBreakpoint.getCondition().getExpression() );
}
catch( CDIException e ) {
}
getBreakpointNotifier().breakpointChanged( getDebugTarget(), breakpoint, map );
} }
} }
@ -623,4 +562,8 @@ public class CBreakpointManager implements ICDIEventListener, IAdaptable {
private IFile getExecFile() { private IFile getExecFile() {
return getDebugTarget().getExecFile(); return getDebugTarget().getExecFile();
} }
private CBreakpointNotifier getBreakpointNotifier() {
return CBreakpointNotifier.getInstance();
}
} }

View file

@ -0,0 +1,81 @@
/**********************************************************************
* Copyright (c) 2004 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
***********************************************************************/
package org.eclipse.cdt.debug.internal.core;
import java.util.Map;
import org.eclipse.cdt.debug.core.CDebugCorePlugin;
import org.eclipse.cdt.debug.core.ICBreakpointListener;
import org.eclipse.debug.core.model.IBreakpoint;
import org.eclipse.debug.core.model.IDebugTarget;
public class CBreakpointNotifier implements ICBreakpointListener {
private static CBreakpointNotifier fInstance;
public static CBreakpointNotifier getInstance() {
if ( fInstance == null ) {
fInstance = new CBreakpointNotifier();
}
return fInstance;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.cdt.debug.core.ICBreakpointListener#installingBreakpoint(org.eclipse.debug.core.model.IDebugTarget,
* org.eclipse.debug.core.model.IBreakpoint)
*/
public boolean installingBreakpoint( IDebugTarget target, IBreakpoint breakpoint ) {
boolean result = true;
Object[] listeners = CDebugCorePlugin.getDefault().getCBreakpointListeners();
for( int i = 0; i < listeners.length; ++i ) {
if ( !((ICBreakpointListener)listeners[i]).installingBreakpoint( target, breakpoint ) )
result = false;
}
return result;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.cdt.debug.core.ICBreakpointListener#breakpointInstalled(org.eclipse.debug.core.model.IDebugTarget,
* org.eclipse.debug.core.model.IBreakpoint)
*/
public void breakpointInstalled( IDebugTarget target, IBreakpoint breakpoint ) {
Object[] listeners = CDebugCorePlugin.getDefault().getCBreakpointListeners();
for( int i = 0; i < listeners.length; ++i )
((ICBreakpointListener)listeners[i]).breakpointInstalled( target, breakpoint );
}
/*
* (non-Javadoc)
*
* @see org.eclipse.cdt.debug.core.ICBreakpointListener#breakpointChanged(org.eclipse.debug.core.model.IDebugTarget,
* org.eclipse.debug.core.model.IBreakpoint)
*/
public void breakpointChanged( IDebugTarget target, IBreakpoint breakpoint, Map attributes ) {
Object[] listeners = CDebugCorePlugin.getDefault().getCBreakpointListeners();
for( int i = 0; i < listeners.length; ++i )
((ICBreakpointListener)listeners[i]).breakpointChanged( target, breakpoint, attributes );
}
/*
* (non-Javadoc)
*
* @see org.eclipse.cdt.debug.core.ICBreakpointListener#breakpointRemoved(org.eclipse.debug.core.model.IDebugTarget,
* org.eclipse.debug.core.model.IBreakpoint)
*/
public void breakpointRemoved( IDebugTarget target, IBreakpoint breakpoint ) {
Object[] listeners = CDebugCorePlugin.getDefault().getCBreakpointListeners();
for( int i = 0; i < listeners.length; ++i )
((ICBreakpointListener)listeners[i]).breakpointRemoved( target, breakpoint );
}
}

View file

@ -0,0 +1,136 @@
/*******************************************************************************
* Copyright (c) 2000, 2003 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.debug.internal.core;
/**
* Local version of org.eclipse.jface.util.ListenerList (modified)s
*/
public class ListenerList {
/**
* The current number of listeners.
* Maintains invariant: 0 <= fSize <= listeners.length.
*/
private int fSize;
/**
* The list of listeners. Initially <code>null</code> but initialized
* to an array of size capacity the first time a listener is added.
* Maintains invariant: listeners != null if and only if fSize != 0
*/
private Object[] fListeners= null;
/**
* The empty array singleton instance, returned by getListeners()
* when size == 0.
*/
private static final Object[] EmptyArray= new Object[0];
/**
* Creates a listener list with the given initial capacity.
*
* @param capacity the number of listeners which this list can initially accept
* without growing its internal representation; must be at least 1
*/
public ListenerList(int capacity) {
if (capacity < 1) {
throw new IllegalArgumentException();
}
fListeners= new Object[capacity];
fSize= 0;
}
/**
* Adds a listener to the list.
* Has no effect if an identical listener is already registered.
*
* @param listener a listener
*/
public synchronized void add(Object listener) {
if (listener == null) {
throw new IllegalArgumentException();
}
// check for duplicates using identity
for (int i= 0; i < fSize; ++i) {
if (fListeners[i] == listener) {
return;
}
}
// grow array if necessary
if (fSize == fListeners.length) {
Object[] temp= new Object[(fSize * 2) + 1];
System.arraycopy(fListeners, 0, temp, 0, fSize);
fListeners= temp;
}
fListeners[fSize++]= listener;
}
/**
* Returns an array containing all the registered listeners.
* The resulting array is unaffected by subsequent adds or removes.
* If there are no listeners registered, the result is an empty array
* singleton instance (no garbage is created).
* Use this method when notifying listeners, so that any modifications
* to the listener list during the notification will have no effect on the
* notification itself.
*/
public synchronized Object[] getListeners() {
if (fSize == 0) {
return EmptyArray;
}
Object[] result= new Object[fSize];
System.arraycopy(fListeners, 0, result, 0, fSize);
return result;
}
/**
* Removes a listener from the list.
* Has no effect if an identical listener was not already registered.
*
* @param listener a listener
*/
public synchronized void remove(Object listener) {
if (listener == null) {
throw new IllegalArgumentException();
}
for (int i= 0; i < fSize; ++i) {
if (fListeners[i] == listener) {
if (--fSize == 0) {
fListeners= new Object[1];
} else {
if (i < fSize) {
fListeners[i]= fListeners[fSize];
}
fListeners[fSize]= null;
}
return;
}
}
}
/**
* Removes all the listeners from the list.
*/
public void removeAll() {
fListeners= new Object[0];
fSize= 0;
}
/**
* Returns the number of registered listeners
*
* @return the number of registered listeners
*/
public int size() {
return fSize;
}
}

View file

@ -197,19 +197,20 @@ public abstract class CBreakpoint extends Breakpoint implements ICBreakpoint, ID
abstract protected String getMarkerMessage() throws CoreException; abstract protected String getMarkerMessage() throws CoreException;
/** /* (non-Javadoc)
* Resets the install count of this breakpoint * @see org.eclipse.cdt.debug.core.model.ICBreakpoint#resetInstallCount()
*/ */
public synchronized void resetInstallCount() throws CoreException { public synchronized void resetInstallCount() throws CoreException {
setAttribute( INSTALL_COUNT, 0 ); setAttribute( INSTALL_COUNT, 0 );
} }
/** /* (non-Javadoc)
* Increments the install count of this breakpoint * @see org.eclipse.cdt.debug.core.model.ICBreakpoint#incrementInstallCount()
*/ */
public synchronized void incrementInstallCount() throws CoreException { public synchronized int incrementInstallCount() throws CoreException {
int count = getInstallCount(); int count = getInstallCount();
setAttribute( INSTALL_COUNT, count + 1 ); setAttribute( INSTALL_COUNT, ++count );
return count;
} }
/** /**
@ -220,14 +221,15 @@ public abstract class CBreakpoint extends Breakpoint implements ICBreakpoint, ID
return ensureMarker().getAttribute( INSTALL_COUNT, 0 ); return ensureMarker().getAttribute( INSTALL_COUNT, 0 );
} }
/** /* (non-Javadoc)
* Decrements the install count of this breakpoint. * @see org.eclipse.cdt.debug.core.model.ICBreakpoint#decrementInstallCount()
*/ */
public synchronized void decrementInstallCount() throws CoreException { public synchronized int decrementInstallCount() throws CoreException {
int count = getInstallCount(); int count = getInstallCount();
if ( count > 0 ) { if ( count > 0 ) {
setAttribute( INSTALL_COUNT, count - 1 ); setAttribute( INSTALL_COUNT, --count );
} }
return count;
} }
/* /*

View file

@ -783,7 +783,7 @@ public class CDebugTarget extends CDebugElement
catch( DebugException e ) catch( DebugException e )
{ {
} }
DebugPlugin.getDefault().getBreakpointManager().fireBreakpointChanged( breakpoint ); // DebugPlugin.getDefault().getBreakpointManager().fireBreakpointChanged( breakpoint );
} }
} }

View file

@ -1,3 +1,13 @@
2004-04-19 Mikhail Khodjaiants
Fix for bug 58711: Breakpoint race condition.
To avoid race condition all breakpoint marker updates (like increment/decrement the install count,
enable/disable etc.) should be done in the UI thread. At the same time installing breakpoint
at a target should be synchronized with other gdb commands (bug 58711).
A special listener (CBreakpointUpdater) has been added to receive notifications from the event
thread and post marker updates to the UI thread.
* CDebugUIPlugin.java
* CBreakpointUpdater.java: new
2004-04-16 Mikhail Khodjaiants 2004-04-16 Mikhail Khodjaiants
Implementing retargettable actions for Disassembly view. Implementing retargettable actions for Disassembly view.
* plugin.xml * plugin.xml

View file

@ -0,0 +1,122 @@
/**********************************************************************
* Copyright (c) 2004 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
***********************************************************************/
package org.eclipse.cdt.debug.internal.ui;
import java.util.Map;
import org.eclipse.cdt.debug.core.ICBreakpointListener;
import org.eclipse.cdt.debug.core.model.ICBreakpoint;
import org.eclipse.cdt.debug.ui.CDebugUIPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.model.IBreakpoint;
import org.eclipse.debug.core.model.IDebugTarget;
import org.eclipse.debug.internal.ui.DebugUIPlugin;
import org.eclipse.swt.widgets.Display;
/**
* Provides UI-related handles for the breakpoint events.
*/
public class CBreakpointUpdater implements ICBreakpointListener {
private static CBreakpointUpdater fInstance;
public static CBreakpointUpdater getInstance() {
if ( fInstance == null ) {
fInstance = new CBreakpointUpdater();
}
return fInstance;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.cdt.debug.core.ICBreakpointListener#installingBreakpoint(org.eclipse.debug.core.model.IDebugTarget,
* org.eclipse.debug.core.model.IBreakpoint)
*/
public boolean installingBreakpoint( IDebugTarget target, IBreakpoint breakpoint ) {
return true;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.cdt.debug.core.ICBreakpointListener#breakpointInstalled(org.eclipse.debug.core.model.IDebugTarget,
* org.eclipse.debug.core.model.IBreakpoint)
*/
public void breakpointInstalled( IDebugTarget target, final IBreakpoint breakpoint ) {
asyncExec( new Runnable() {
public void run() {
try {
((ICBreakpoint)breakpoint).incrementInstallCount();
}
catch( CoreException e ) {
CDebugUIPlugin.log( e.getStatus() );
}
}
} );
}
/*
* (non-Javadoc)
*
* @see org.eclipse.cdt.debug.core.ICBreakpointListener#breakpointChanged(org.eclipse.debug.core.model.IDebugTarget,
* org.eclipse.debug.core.model.IBreakpoint, java.util.Map)
*/
public void breakpointChanged( IDebugTarget target, final IBreakpoint breakpoint, final Map attributes ) {
asyncExec( new Runnable() {
public void run() {
try {
Boolean enabled = (Boolean)attributes.get( IBreakpoint.ENABLED );
breakpoint.setEnabled( (enabled != null) ? enabled.booleanValue() : false );
Integer ignoreCount = (Integer)attributes.get( ICBreakpoint.IGNORE_COUNT );
((ICBreakpoint)breakpoint).setIgnoreCount( (ignoreCount != null) ? ignoreCount.intValue() : 0 );
String condition = (String)attributes.get( ICBreakpoint.CONDITION );
((ICBreakpoint)breakpoint).setCondition( (condition != null) ? condition : "" ); //$NON-NLS-1$
}
catch( CoreException e ) {
CDebugUIPlugin.log( e.getStatus() );
}
}
} );
}
/*
* (non-Javadoc)
*
* @see org.eclipse.cdt.debug.core.ICBreakpointListener#breakpointRemoved(org.eclipse.debug.core.model.IDebugTarget,
* org.eclipse.debug.core.model.IBreakpoint)
*/
public void breakpointRemoved( IDebugTarget target, final IBreakpoint breakpoint ) {
asyncExec( new Runnable() {
public void run() {
try {
int installCount = ((ICBreakpoint)breakpoint).decrementInstallCount();
if ( installCount == 0 )
breakpoint.delete();
}
catch( CoreException e ) {
CDebugUIPlugin.log( e.getStatus() );
}
}
} );
}
public void dispose() {
}
private void asyncExec( Runnable r ) {
Display display = DebugUIPlugin.getStandardDisplay();
if ( display != null )
display.asyncExec( r );
}
}

View file

@ -1,9 +1,13 @@
/* /**********************************************************************
*(c) Copyright QNX Software Systems Ltd. 2002. * Copyright (c) 2004 QNX Software Systems and others.
* All Rights Reserved. * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
* *
*/ * Contributors:
* QNX Software Systems - Initial API and implementation
***********************************************************************/
package org.eclipse.cdt.debug.internal.ui; package org.eclipse.cdt.debug.internal.ui;
import java.util.HashMap; import java.util.HashMap;
@ -31,9 +35,7 @@ import org.eclipse.swt.graphics.Image;
import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorInput;
/** /**
* Enter type comment. * @see IDebugModelPresentation
*
* @since: Feb 4, 2004
*/ */
public class CDebugModelPresentation extends LabelProvider implements IDebugModelPresentation { public class CDebugModelPresentation extends LabelProvider implements IDebugModelPresentation {

View file

@ -1,3 +1,13 @@
/**********************************************************************
* Copyright (c) 2004 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
***********************************************************************/
package org.eclipse.cdt.debug.ui; package org.eclipse.cdt.debug.ui;
import java.text.MessageFormat; import java.text.MessageFormat;
@ -7,10 +17,10 @@ import java.util.MissingResourceException;
import java.util.ResourceBundle; import java.util.ResourceBundle;
import org.eclipse.cdt.debug.core.CDebugCorePlugin; import org.eclipse.cdt.debug.core.CDebugCorePlugin;
import org.eclipse.cdt.debug.core.IAsyncExecutor;
import org.eclipse.cdt.debug.core.model.ISwitchToFrame; import org.eclipse.cdt.debug.core.model.ISwitchToFrame;
import org.eclipse.cdt.debug.core.model.ISwitchToThread; import org.eclipse.cdt.debug.core.model.ISwitchToThread;
import org.eclipse.cdt.debug.core.sourcelookup.IDisassemblyStorage; import org.eclipse.cdt.debug.core.sourcelookup.IDisassemblyStorage;
import org.eclipse.cdt.debug.internal.ui.CBreakpointUpdater;
import org.eclipse.cdt.debug.internal.ui.CDTDebugModelPresentation; import org.eclipse.cdt.debug.internal.ui.CDTDebugModelPresentation;
import org.eclipse.cdt.debug.internal.ui.CDebugImageDescriptorRegistry; import org.eclipse.cdt.debug.internal.ui.CDebugImageDescriptorRegistry;
import org.eclipse.cdt.debug.internal.ui.ColorManager; import org.eclipse.cdt.debug.internal.ui.ColorManager;
@ -61,8 +71,7 @@ import org.eclipse.ui.plugin.AbstractUIPlugin;
*/ */
public class CDebugUIPlugin extends AbstractUIPlugin public class CDebugUIPlugin extends AbstractUIPlugin
implements ISelectionListener, implements ISelectionListener,
IDebugEventSetListener, IDebugEventSetListener
IAsyncExecutor
{ {
//The shared instance. //The shared instance.
private static CDebugUIPlugin plugin; private static CDebugUIPlugin plugin;
@ -330,6 +339,7 @@ public class CDebugUIPlugin extends AbstractUIPlugin
public void shutdown() throws CoreException public void shutdown() throws CoreException
{ {
DebugPlugin.getDefault().removeDebugEventListener( this ); DebugPlugin.getDefault().removeDebugEventListener( this );
CDebugCorePlugin.getDefault().removeCBreakpointListener( CBreakpointUpdater.getInstance() );
// TODO: PR 52155, this is big hammer approach, but it is ok for // TODO: PR 52155, this is big hammer approach, but it is ok for
// Since the code will be remove when we align ourselves // Since the code will be remove when we align ourselves
// with Eclipse-3.0 // with Eclipse-3.0
@ -347,7 +357,6 @@ public class CDebugUIPlugin extends AbstractUIPlugin
{ {
fImageDescriptorRegistry.dispose(); fImageDescriptorRegistry.dispose();
} }
CDebugCorePlugin.getDefault().setAsyncExecutor( null );
super.shutdown(); super.shutdown();
} }
@ -362,7 +371,7 @@ public class CDebugUIPlugin extends AbstractUIPlugin
{ {
ww.getSelectionService().addSelectionListener( IDebugUIConstants.ID_DEBUG_VIEW, this ); ww.getSelectionService().addSelectionListener( IDebugUIConstants.ID_DEBUG_VIEW, this );
} }
CDebugCorePlugin.getDefault().setAsyncExecutor( this ); CDebugCorePlugin.getDefault().addCBreakpointListener( CBreakpointUpdater.getInstance() );
DebugPlugin.getDefault().addDebugEventListener( this ); DebugPlugin.getDefault().addDebugEventListener( this );
} }
@ -513,18 +522,6 @@ public class CDebugUIPlugin extends AbstractUIPlugin
return fDisassemblyDocumentProvider; return fDisassemblyDocumentProvider;
} }
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.IAsyncExecutor#asyncExec(Runnable)
*/
public void asyncExec( Runnable runnable )
{
Display display = getStandardDisplay();
if ( display != null )
{
display.asyncExec( runnable );
}
}
public static IPersistableSourceLocator createDefaultSourceLocator() public static IPersistableSourceLocator createDefaultSourceLocator()
{ {
return new DefaultSourceLocator(); return new DefaultSourceLocator();