1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-23 22:52:11 +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
Display global variable name in the error message when the "Add Globals" action fails.
* CDebugModel.java

View file

@ -1,9 +1,13 @@
/*
*(c) Copyright QNX Software Systems Ltd. 2002.
* All Rights Reserved.
/**********************************************************************
* 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.core;
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.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.breakpoints.CBreakpoint;
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;
/**
* 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.
*/
public static final int INTERNAL_ERROR = 1000;
//The shared instance.
/**
* The shared instance.
*/
private static CDebugCorePlugin plugin;
private static ResourceBundle fgResourceBundle;
private HashMap fDebugConfigurations;
private IAsyncExecutor fAsyncExecutor = null;
/**
* Breakpoint listener list.
*/
private ListenerList fBreakpointListeners;
private SessionManager fSessionManager = null;
static {
try {
fgResourceBundle = ResourceBundle.getBundle("org.eclipse.cdt.debug.core.CDebugCorePluginResources"); //$NON-NLS-1$
} catch (MissingResourceException x) {
fgResourceBundle = ResourceBundle.getBundle( "org.eclipse.cdt.debug.core.CDebugCorePluginResources" ); //$NON-NLS-1$
}
catch( MissingResourceException x ) {
fgResourceBundle = null;
}
}
/**
* The constructor.
*/
public CDebugCorePlugin( IPluginDescriptor descriptor )
{
public CDebugCorePlugin( IPluginDescriptor descriptor ) {
super( descriptor );
plugin = this;
}
@ -72,8 +83,7 @@ public class CDebugCorePlugin extends Plugin
*
* @return the shared instance
*/
public static CDebugCorePlugin getDefault()
{
public static CDebugCorePlugin getDefault() {
return plugin;
}
@ -82,8 +92,7 @@ public class CDebugCorePlugin extends Plugin
*
* @return the workspace instance
*/
public static IWorkspace getWorkspace()
{
public static IWorkspace getWorkspace() {
return ResourcesPlugin.getWorkspace();
}
@ -92,10 +101,8 @@ public class CDebugCorePlugin extends Plugin
*
* @return the unique identifier of this plugin
*/
public static String getUniqueIdentifier()
{
if ( getDefault() == null )
{
public static String getUniqueIdentifier() {
if ( getDefault() == null ) {
// If the default instance is not yet initialized,
// return a static identifier. This identifier must
// match the plugin id defined in plugin.xml
@ -104,23 +111,26 @@ public class CDebugCorePlugin extends Plugin
return getDefault().getDescriptor().getUniqueIdentifier();
}
public static String getResourceString(String key) {
public static String getResourceString( String key ) {
try {
return fgResourceBundle.getString(key);
} catch (MissingResourceException e) {
return fgResourceBundle.getString( key );
}
catch( MissingResourceException e ) {
return "!" + key + "!"; //$NON-NLS-1$ //$NON-NLS-2$
} catch (NullPointerException e) {
}
catch( NullPointerException e ) {
return "#" + key + "#"; //$NON-NLS-1$ //$NON-NLS-2$
}
}
public static String getFormattedString(String key, String arg) {
return MessageFormat.format(getResourceString(key), new String[] { arg });
public static String getFormattedString( String key, String arg ) {
return MessageFormat.format( getResourceString( key ), new String[]{ arg } );
}
public static String getFormattedString(String key, String[] args) {
return MessageFormat.format(getResourceString(key), args);
public static String getFormattedString( String key, String[] args ) {
return MessageFormat.format( getResourceString( key ), args );
}
public static ResourceBundle getResourceBundle() {
return fgResourceBundle;
}
@ -130,15 +140,12 @@ public class CDebugCorePlugin extends Plugin
*
* @param t throwable to log
*/
public static void log( Throwable t )
{
public static void log( Throwable t ) {
Throwable top = t;
if ( t instanceof DebugException )
{
if ( t instanceof DebugException ) {
DebugException de = (DebugException)t;
IStatus status = de.getStatus();
if ( status.getException() != null )
{
if ( status.getException() != null ) {
top = status.getException();
}
}
@ -152,52 +159,46 @@ public class CDebugCorePlugin extends Plugin
*
* @param status status to log
*/
public static void log( IStatus status )
{
public static void log( IStatus status ) {
getDefault().getLog().log( status );
}
/**
* Logs the specified message with this plug-in's log.
*
* @param status status to log
*/
public static void log( String message )
{
getDefault().getLog().log( new Status( IStatus.ERROR,
CDebugModel.getPluginIdentifier(),
INTERNAL_ERROR,
message,
null ) );
public static void log( String message ) {
getDefault().getLog().log( new Status( IStatus.ERROR, CDebugModel.getPluginIdentifier(), INTERNAL_ERROR, message, null ) );
}
private void initializeDebugConfiguration() {
IPluginDescriptor descriptor= getDefault().getDescriptor();
IExtensionPoint extensionPoint= descriptor.getExtensionPoint("CDebugger"); //$NON-NLS-1$
IConfigurationElement[] infos= extensionPoint.getConfigurationElements();
fDebugConfigurations = new HashMap(infos.length);
for (int i= 0; i < infos.length; i++) {
IPluginDescriptor descriptor = getDefault().getDescriptor();
IExtensionPoint extensionPoint = descriptor.getExtensionPoint( "CDebugger" ); //$NON-NLS-1$
IConfigurationElement[] infos = extensionPoint.getConfigurationElements();
fDebugConfigurations = new HashMap( infos.length );
for( int i = 0; i < infos.length; i++ ) {
IConfigurationElement configurationElement = infos[i];
DebugConfiguration configType = new DebugConfiguration(configurationElement);
fDebugConfigurations.put(configType.getID(), configType);
}
DebugConfiguration configType = new DebugConfiguration( configurationElement );
fDebugConfigurations.put( configType.getID(), configType );
}
}
public ICDebugConfiguration[] getDebugConfigurations() {
if (fDebugConfigurations == null) {
if ( fDebugConfigurations == null ) {
initializeDebugConfiguration();
}
return (ICDebugConfiguration[]) fDebugConfigurations.values().toArray(new ICDebugConfiguration[0]);
return (ICDebugConfiguration[])fDebugConfigurations.values().toArray( new ICDebugConfiguration[0] );
}
public ICDebugConfiguration getDebugConfiguration(String id) throws CoreException {
if (fDebugConfigurations == null) {
public ICDebugConfiguration getDebugConfiguration( String id ) throws CoreException {
if ( fDebugConfigurations == null ) {
initializeDebugConfiguration();
}
ICDebugConfiguration dbgCfg = (ICDebugConfiguration) fDebugConfigurations.get(id);
ICDebugConfiguration dbgCfg = (ICDebugConfiguration)fDebugConfigurations.get( id );
if ( dbgCfg == null ) {
IStatus status = new Status(IStatus.ERROR, getUniqueIdentifier(), 100, CDebugCorePlugin.getResourceString("core.CDebugCorePlugin.No_such_debugger"), null); //$NON-NLS-1$
throw new CoreException(status);
IStatus status = new Status( IStatus.ERROR, getUniqueIdentifier(), 100, CDebugCorePlugin.getResourceString( "core.CDebugCorePlugin.No_such_debugger" ), null ); //$NON-NLS-1$
throw new CoreException( status );
}
return dbgCfg;
}
@ -205,9 +206,9 @@ public class CDebugCorePlugin extends Plugin
/* (non-Javadoc)
* @see org.eclipse.core.runtime.Plugin#shutdown()
*/
public void shutdown() throws CoreException
{
public void shutdown() throws CoreException {
setSessionManager( null );
disposeBreakpointListenersList();
resetBreakpointsInstallCount();
super.shutdown();
}
@ -215,63 +216,79 @@ public class CDebugCorePlugin extends Plugin
/* (non-Javadoc)
* @see org.eclipse.core.runtime.Plugin#startup()
*/
public void startup() throws CoreException
{
public void startup() throws CoreException {
super.startup();
createBreakpointListenersList();
resetBreakpointsInstallCount();
setSessionManager( new SessionManager() );
}
protected void resetBreakpointsInstallCount()
{
protected void resetBreakpointsInstallCount() {
IBreakpointManager bm = DebugPlugin.getDefault().getBreakpointManager();
IBreakpoint[] breakpoints = bm.getBreakpoints( getUniqueIdentifier() );
for ( int i = 0; i < breakpoints.length; ++i )
{
if ( breakpoints[i] instanceof CBreakpoint )
{
try
{
for( int i = 0; i < breakpoints.length; ++i ) {
if ( breakpoints[i] instanceof CBreakpoint ) {
try {
((CBreakpoint)breakpoints[i]).resetInstallCount();
}
catch( CoreException e )
{
catch( CoreException e ) {
log( e.getStatus() );
}
}
}
}
public void setAsyncExecutor( IAsyncExecutor executor )
{
fAsyncExecutor = executor;
}
public void asyncExec( Runnable runnable )
{
if ( fAsyncExecutor != null )
fAsyncExecutor.asyncExec( runnable );
}
protected SessionManager getSessionManager()
{
protected SessionManager getSessionManager() {
return fSessionManager;
}
protected void setSessionManager( SessionManager sm )
{
protected void setSessionManager( SessionManager sm ) {
if ( fSessionManager != null )
fSessionManager.dispose();
fSessionManager = sm;
}
public void saveCommonSourceLocations( ICSourceLocation[] locations )
{
public void saveCommonSourceLocations( ICSourceLocation[] 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 ) );
}
}
/**
* 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
*/
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;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.eclipse.cdt.debug.core.CDIDebugModel;
@ -87,7 +88,7 @@ public class CBreakpointManager implements ICDIEventListener, IAdaptable {
return (ICBreakpoint)fCDIBreakpoints.get( cdiBreakpoint );
}
protected void removeCBreakpoint( ICBreakpoint breakpoint ) {
protected synchronized void removeCBreakpoint( ICBreakpoint breakpoint ) {
if ( breakpoint != null ) {
ICDIBreakpoint cdiBreakpoint = (ICDIBreakpoint)fCBreakpoints.remove( breakpoint );
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 ) {
ICBreakpoint breakpoint = (ICBreakpoint)fCDIBreakpoints.remove( cdiBreakpoint );
if ( breakpoint != null )
@ -257,18 +258,8 @@ public class CBreakpointManager implements ICDIEventListener, IAdaptable {
return 0;
}
public void setBreakpoint( final ICBreakpoint breakpoint ) throws DebugException {
Runnable runnable = new Runnable() {
public void run() {
try {
doSetBreakpoint( breakpoint );
}
catch( DebugException e ) {
}
}
};
CDebugCorePlugin.getDefault().asyncExec( runnable );
public void setBreakpoint( ICBreakpoint breakpoint ) throws DebugException {
doSetBreakpoint( breakpoint );
}
protected void doSetBreakpoint( ICBreakpoint breakpoint ) throws DebugException {
@ -302,16 +293,7 @@ public class CBreakpointManager implements ICDIEventListener, IAdaptable {
}
public void removeBreakpoint( final ICBreakpoint breakpoint ) throws DebugException {
Runnable runnable = new Runnable() {
public void run() {
try {
doRemoveBreakpoint( breakpoint );
}
catch( DebugException e ) {
}
}
};
CDebugCorePlugin.getDefault().asyncExec( runnable );
doRemoveBreakpoint( breakpoint );
}
protected void doRemoveBreakpoint( ICBreakpoint breakpoint ) throws DebugException {
@ -328,17 +310,7 @@ public class CBreakpointManager implements ICDIEventListener, IAdaptable {
}
public void changeBreakpointProperties( final ICBreakpoint breakpoint, final IMarkerDelta delta ) throws DebugException {
Runnable runnable = new Runnable() {
public void run() {
try {
doChangeBreakpointProperties( breakpoint, delta );
}
catch( DebugException e ) {
}
}
};
CDebugCorePlugin.getDefault().asyncExec( runnable );
doChangeBreakpointProperties( breakpoint, delta );
}
protected void doChangeBreakpointProperties( ICBreakpoint breakpoint, IMarkerDelta delta ) throws DebugException {
@ -370,16 +342,10 @@ public class CBreakpointManager implements ICDIEventListener, IAdaptable {
}
private void handleBreakpointCreatedEvent( final ICDIBreakpoint cdiBreakpoint ) {
Runnable runnable = new Runnable() {
public void run() {
if ( cdiBreakpoint instanceof ICDILocationBreakpoint )
doHandleLocationBreakpointCreatedEvent( (ICDILocationBreakpoint)cdiBreakpoint );
else if ( cdiBreakpoint instanceof ICDIWatchpoint )
doHandleWatchpointCreatedEvent( (ICDIWatchpoint)cdiBreakpoint );
}
};
CDebugCorePlugin.getDefault().asyncExec( runnable );
if ( cdiBreakpoint instanceof ICDILocationBreakpoint )
doHandleLocationBreakpointCreatedEvent( (ICDILocationBreakpoint)cdiBreakpoint );
else if ( cdiBreakpoint instanceof ICDIWatchpoint )
doHandleWatchpointCreatedEvent( (ICDIWatchpoint)cdiBreakpoint );
}
protected void doHandleLocationBreakpointCreatedEvent( ICDILocationBreakpoint cdiBreakpoint ) {
@ -410,12 +376,7 @@ public class CBreakpointManager implements ICDIEventListener, IAdaptable {
}
}
if ( breakpoint != null ) {
try {
((CBreakpoint)breakpoint).incrementInstallCount();
}
catch( CoreException e ) {
CDebugCorePlugin.log( e.getStatus() );
}
getBreakpointNotifier().breakpointInstalled( getDebugTarget(), breakpoint );
}
}
@ -431,60 +392,38 @@ public class CBreakpointManager implements ICDIEventListener, IAdaptable {
}
}
if ( breakpoint != null ) {
try {
((CBreakpoint)breakpoint).incrementInstallCount();
}
catch( CoreException e ) {
CDebugCorePlugin.log( e.getStatus() );
}
getBreakpointNotifier().breakpointInstalled( getDebugTarget(), breakpoint );
}
}
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 );
getBreakpointMap().removeCDIBreakpoint( cdiBreakpoint );
if ( breakpoint != null ) {
getBreakpointMap().removeCDIBreakpoint( breakpoint, cdiBreakpoint );
try {
((CBreakpoint)breakpoint).decrementInstallCount();
}
catch( CoreException e ) {
CDebugCorePlugin.log( e.getStatus() );
}
getBreakpointNotifier().breakpointRemoved( getDebugTarget(), breakpoint );
}
}
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 );
if ( breakpoint != null ) {
Map map = new HashMap( 3 );
try {
breakpoint.setEnabled( cdiBreakpoint.isEnabled() );
breakpoint.setIgnoreCount( cdiBreakpoint.getCondition().getIgnoreCount() );
breakpoint.setCondition( cdiBreakpoint.getCondition().getExpression() );
map.put( IBreakpoint.ENABLED, new Boolean( cdiBreakpoint.isEnabled() ) );
}
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() {
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;
/**
* Resets the install count of this breakpoint
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.ICBreakpoint#resetInstallCount()
*/
public synchronized void resetInstallCount() throws CoreException {
setAttribute( INSTALL_COUNT, 0 );
}
/**
* Increments the install count of this breakpoint
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.ICBreakpoint#incrementInstallCount()
*/
public synchronized void incrementInstallCount() throws CoreException {
public synchronized int incrementInstallCount() throws CoreException {
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 );
}
/**
* Decrements the install count of this breakpoint.
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.ICBreakpoint#decrementInstallCount()
*/
public synchronized void decrementInstallCount() throws CoreException {
public synchronized int decrementInstallCount() throws CoreException {
int count = getInstallCount();
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 )
{
}
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
Implementing retargettable actions for Disassembly view.
* 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.
* All Rights Reserved.
/**********************************************************************
* 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.HashMap;
@ -31,9 +35,7 @@ import org.eclipse.swt.graphics.Image;
import org.eclipse.ui.IEditorInput;
/**
* Enter type comment.
*
* @since: Feb 4, 2004
* @see 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;
import java.text.MessageFormat;
@ -7,10 +17,10 @@ import java.util.MissingResourceException;
import java.util.ResourceBundle;
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.ISwitchToThread;
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.CDebugImageDescriptorRegistry;
import org.eclipse.cdt.debug.internal.ui.ColorManager;
@ -61,8 +71,7 @@ import org.eclipse.ui.plugin.AbstractUIPlugin;
*/
public class CDebugUIPlugin extends AbstractUIPlugin
implements ISelectionListener,
IDebugEventSetListener,
IAsyncExecutor
IDebugEventSetListener
{
//The shared instance.
private static CDebugUIPlugin plugin;
@ -330,6 +339,7 @@ public class CDebugUIPlugin extends AbstractUIPlugin
public void shutdown() throws CoreException
{
DebugPlugin.getDefault().removeDebugEventListener( this );
CDebugCorePlugin.getDefault().removeCBreakpointListener( CBreakpointUpdater.getInstance() );
// TODO: PR 52155, this is big hammer approach, but it is ok for
// Since the code will be remove when we align ourselves
// with Eclipse-3.0
@ -347,7 +357,6 @@ public class CDebugUIPlugin extends AbstractUIPlugin
{
fImageDescriptorRegistry.dispose();
}
CDebugCorePlugin.getDefault().setAsyncExecutor( null );
super.shutdown();
}
@ -362,7 +371,7 @@ public class CDebugUIPlugin extends AbstractUIPlugin
{
ww.getSelectionService().addSelectionListener( IDebugUIConstants.ID_DEBUG_VIEW, this );
}
CDebugCorePlugin.getDefault().setAsyncExecutor( this );
CDebugCorePlugin.getDefault().addCBreakpointListener( CBreakpointUpdater.getInstance() );
DebugPlugin.getDefault().addDebugEventListener( this );
}
@ -513,18 +522,6 @@ public class CDebugUIPlugin extends AbstractUIPlugin
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()
{
return new DefaultSourceLocator();