Bug 186172 - NullPointerException in debugger console
Summary: NullPointerException in debugger console
Status: RESOLVED FIXED
Alias: None
Product: CDT
Classification: Tools
Component: cdt-debug (show other bugs)
Version: 4.0   Edit
Hardware: PC Linux
: P3 normal (vote)
Target Milestone: 4.0.3   Edit
Assignee: Anton Leherbauer CLA
QA Contact:
URL:
Whiteboard:
Keywords: contributed
: 214407 (view as bug list)
Depends on:
Blocks:
 
Reported: 2007-05-09 10:50 EDT by Jens Seidel CLA
Modified: 2008-06-22 02:37 EDT (History)
7 users (show)

See Also:


Attachments
4_0 patch (6.36 KB, patch)
2008-01-07 12:57 EST, Elena Laskavaia CLA
bjorn.freeman-benson: iplog+
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Jens Seidel CLA 2007-05-09 10:50:41 EDT
Hi,

I find from time to time the following exception in my log file
(it seems not to affect debugging?):

!ENTRY org.eclipse.ui.console 4 2 2007-05-09 16:12:29.737
!MESSAGE Problems occurred when invoking code from plug-in: "org.eclipse.ui.console".
!STACK 0
java.lang.NullPointerException
  at org.eclipse.cdt.debug.mi.ui.console.actions.MiConsoleVerboseModeAction.<init>(MiConsoleVerboseModeAction.java:32)
  at org.eclipse.cdt.debug.mi.ui.console.MiConsolePageParticipant.init(MiConsolePageParticipant.java:70)
  at org.eclipse.ui.internal.console.ConsoleView$3.run(ConsoleView.java:312)
  at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:37)
  at org.eclipse.ui.internal.console.ConsoleView.doCreatePage(ConsoleView.java:310)
  at org.eclipse.ui.part.PageBookView.createPage(PageBookView.java:399)
  at org.eclipse.ui.part.PageBookView.partActivated(PageBookView.java:741)
  at org.eclipse.ui.internal.console.ConsoleView$4.run(ConsoleView.java:380)
  at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:35)
  at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:123)
  at org.eclipse.swt.widgets.Display.runAsyncMessages(Display.java:3233)
  at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:2926)
  at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2337)
  at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2301)
  at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2176)
  at org.eclipse.ui.internal.Workbench$4.run(Workbench.java:463)
  at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:289)
  at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:458)
  at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
  at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:101)
  at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:146)
  at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:106)
  at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:76)
  at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:356)
  at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:171)
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
  at java.lang.reflect.Method.invoke(Unknown Source)
  at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:476)
  at org.eclipse.equinox.launcher.Main.basicRun(Main.java:416)
  at org.eclipse.equinox.launcher.Main.run(Main.java:1141)

It is always followed by
!ENTRY org.eclipse.ui.console 4 120 2007-05-09 16:12:29.739
!MESSAGE Error logged from Console plug-in: 
!STACK 0
java.lang.NullPointerException

with exact the same stacktrace.

I use CDT 4.0RC0 and eclipse 3.3M6
Comment 1 Andreas Schik CLA 2007-08-09 12:52:17 EDT
I can see this as well in the released versions (3.3, 4.0.0). Here it happens all the time.
After searching for a while I found the reason. It is a concurrency problem in class org.eclipse.cdt.debug.mi.core.GDBProcess. Its constructor calls (of course) super(), which is org.eclipse.debug.core.model.RuntimeProcess. This constructor calls launch.addProcess(this) which triggers creation of the debugger console and thus creation of the MiConsoleVerboseModeAction toolbar item. Unfortunately, this action needs the fTarget member of GDBProcess.
The reason why you see the problem only once in a while is, that the console creation is event triggered and sometimes the event hits before the constructor of GDBProcess is fully done and sometimes the event hits at a later point in time and everything wil be OK.
I wonder whether calling launch.addProcess(this) in the constructor of RuntimeProcess is a good idea. Shouldn't this be left to the creator of the object? At least org.eclipse.cdt.debug.mi.core.AbstractGDBCDIDebugger calls launch.addProcess again after creating GDBProcess (which does not have any effect as the process is already added to the launch). OTOH, there seem to be to many places where a RuntimeProcess is created and which needed to be changed...
Another solution might be synchronization of GDBProcess (something along those lines, don't know about side effects, though):

public GDBProcess( Target target, ILaunch launch, Process process, String name, Map attributes ) {
	super( launch, process, name, attributes );
	synchronized (this) {
		fTarget = target;
		notifyAll();
	}
}

synchronized public Target getTarget() {
	if (fTarget == null) {
		try {
			wait();
		} catch (InterruptedException e) {
		}
	}
	return fTarget;
}
Comment 2 Nobody - feel free to take it CLA 2007-08-09 13:17:16 EDT
(In reply to comment #1)
Perhaps the better way is to implement the console actions as contributions.
RuntimeProcess belongs to the platform. If you feel it needs improvements, you should submit enhancement requests to the Platform/Debug component. 
Comment 3 Andreas Schik CLA 2007-08-10 03:22:32 EDT
(In reply to comment #2)
> (In reply to comment #1)
> Perhaps the better way is to implement the console actions as contributions.
I actually don't care as long as we get rid of this race condition. But you are probably right on that. As I have said, I quickly drew up something, without caring for side effects. See it as starting point point for a discussion.

> RuntimeProcess belongs to the platform. If you feel it needs improvements, you
> should submit enhancement requests to the Platform/Debug component. 
OK. Thanks for the hint.
Comment 4 Anton Leherbauer CLA 2008-01-07 05:50:42 EST
*** Bug 214407 has been marked as a duplicate of this bug. ***
Comment 5 Elena Laskavaia CLA 2008-01-07 12:57:50 EST
Created attachment 86333 [details]
4_0 patch

Attaching proposed patch.

RuntimeProcess is done very badly, it adds itself to launch and send notification right from constructor, meaning all subclasses would have to  dial with use of uninitiated objects by launch listeners. I added fireChangeEvent at the end of GDBProvess so we can at least receive notification on when it finished initializing. 
Console buttons should have been made as contributions, but it is different bug report and it would not solve synchronization issue anyway.
Comment 6 Anton Leherbauer CLA 2008-01-14 05:59:13 EST
(In reply to comment #5)
> RuntimeProcess is done very badly, it adds itself to launch and send
> notification right from constructor, meaning all subclasses would have to  dial
> with use of uninitiated objects by launch listeners. 

Alena, could you open a bug against Platform/Debug to improve this? Thanks.

I'll apply your patch with one modification: I removed the additional synchronization in GDBProcess. It seems superfluous to me.
Comment 7 Elena Laskavaia CLA 2008-01-14 10:40:10 EST
If there no synchronization Java does not guarantee that two threads would see change in object immediately, meaning if listener running in different thread even it received notification from constructor after target is set getTarget can still return null for this other thread (cached by jvm).
Comment 8 Anton Leherbauer CLA 2008-01-14 11:04:47 EST
(In reply to comment #7)
> If there no synchronization Java does not guarantee that two threads would see
> change in object immediately, meaning if listener running in different thread
> even it received notification from constructor after target is set getTarget
> can still return null for this other thread (cached by jvm).

Right. Declaring the field volatile should be sufficient.
Comment 9 Anton Leherbauer CLA 2008-01-15 04:17:21 EST
Patch applied to 5.0 and 4.0.3.