Community
Participate
Working Groups
What I did to produce this GPF was set the tree selection (by mistake, bug in my code) to a tree item that the wasn't visible at the time. The hidden tree item existed, but it's parent wasn't expanded. Let me know if you'd like a test case - I'll write one and send it up. NOTES: Unhandled exception Type=GPF vmState=0x00000003 ExceptionCode=0xc0000005 ExceptionAddress=0xbfba9aec ContextFlags=0x0001001f Handler1=0x10e01566 Handler2=0x100385f0 Module=C:\WINDOWS\SYSTEM\COMCTL32.DLL Module_base_address=0xbfb90000 Offset_in_DLL=0x00019aec EDI=0x02ccb3ec ESI=0x73f9810c EAX=0x017f07ac EBX=0x017f07ac ECX=0x00000000 EDX=0x00020020 EBP=0x0063eed8 ESP=0x0063eebc EIP=0xbfba9aec Thread: main (priority 5) 0000 com/ibm/swt/win32/OS.CallWindowProc(IIIII)I 0017 com/ibm/swt/widgets/Tree.callWindowProc(III)I 043f com/ibm/swt/widgets/Window.windowProc(III)I 0015 com/ibm/swt/widgets/Display.windowProc(IIII)I 0000 com/ibm/swt/win32/OS.SendMessage(IIII)I 0092 com/ibm/swt/widgets/Tree.setSelection([Lcom/ibm/swt/widgets/TreeItem;)V 00be com/ibm/ive/tools/profiler/ui/methodcalltree/MethodCallTreeViewer.setSelection(Lcom/ibm/ive/tools/profiler/ui/methodcalltree/MethodCallTreeElement;)V 0022 com/ibm/ive/tools/profiler/ui/methodcalltree/MethodCallTreeViewer.domainChanged(Lcom/ibm/jface/elements/DomainEvent;)V 0034 com/ibm/jface/elements/DomainEvent.dispatch(Ljava/lang/Object;)V 000c com/ibm/jface/elements/DefaultDomainModel$1.run()V 000f com/ibm/swt/widgets/RunnableLock.run()V 0022 com/ibm/swt/widgets/Display.runAsyncMessages()Z 0044 com/ibm/swt/widgets/Display.readAndDispatch()Z 0005 com/ibm/jface/util/Utilities.dispatchEventAndSleep(Lcom/ibm/swt/widgets/Display;)V 000a com/ibm/jface/util/Utilities.runEventLoop()V 001c com/ibm/jface/Application.run()V 0063 com/ibm/ive/tools/profiler/ui/presentation/Profiler.main([Ljava/lang/String;)V SN (12/22/99 11:25:02 AM) Please always submit test code. JH (12/22/99 1:46:08 PM) Here's a test case - sorry if it's a little long. I have two classes: TreeGpfTest and TreeNode. TreeGpfTest is mostly scavenged from the SWT examples so it should look somewhat familiar. Running TreeGpfTest will bring up a window with a tree and a button at the bottom. Clicking the button will attempt to ensure that a tree path is expanded and then set the selection to the last item in the path. If the tree path isn't already expanded, then this should cause the GPF. That is, if you bring up the window and hit the button then you'll get the GPF. The code actually GPFs in Tree.setSelection() but changing the code in TreeGpfTest.getTestItem() to look like: if (!testItem.getExpanded()) { if (testItem.getItems().length == 1 && testItem.getItems()[0].getText().equals(falseNodeText)) { // dispose of dummy items TreeItem [] dummyNodes = testItem.getItems (); for (int n = 0; n < dummyNodes.length; n++) dummyNodes[n].dispose (); expandTree (lastItem); } else { testItem.setExpanded(true); } } instead of: if (!testItem.getExpanded()) { expandTree(testItem); } will prevent the GPF. import com.ibm.swt.SWT; import com.ibm.swt.widgets.*; import com.ibm.swt.layout.*; import com.ibm.swt.graphics.*; import com.ibm.swt.events.*; import java.util.*; public class TreeGpfTest implements TreeListener { private Shell shell; private Display display; protected Button runTestButton; private Tree tree; private TreeNode root; static private final String falseNodeText = "falseNode"; static private final int treeDepth = 5; static private final int childrenPerNode = 5; public static void main(String[] args) { new TreeGpfTest().open().run().close(); } private void runSelectionTest() { TreeItem testItem = getTestItem(); TreeItem[] items = new TreeItem[1]; items[0] = testItem; tree.setSelection(items); tree.showItem(testItem); } private TreeItem getTestItem() { TreeItem testItem = null; TreeItem[] items = tree.getItems(); for (int i = 0; i < treeDepth; i++) { testItem = items[childrenPerNode - 1]; if (!testItem.getExpanded()) { expandTree(testItem); } items = testItem.getItems(); } return testItem; } public void expandTree (TreeItem item) { TreeNode node = (TreeNode) item.getData(); Vector children = node.getChildren(); for (int i = 0; i < children.size(); i++) { TreeNode next = (TreeNode) children.elementAt(i); TreeItem nextItem = new TreeItem(item, SWT.NULL); nextItem.setData(next); nextItem.setText(next.getName()); if (next.getChildren().size() > 0) { TreeItem dummyItem = new TreeItem(nextItem, SWT.NULL); dummyItem.setText(falseNodeText); } } } private Shell createShell() { Shell shell = new Shell(); shell.setText("GPF Example"); shell.setBounds(0, 0, 500, 400); shell.setBackground(new Color(255, 255, 255)); shell.setLayout(new GridLayout()); addComponents(shell); return shell; } private TreeGpfTest close () { if ((shell != null) && (!shell.isDisposed ())) shell.dispose (); shell = null; return this; } private TreeGpfTest open () { shell = createShell (); display = shell.getDisplay (); shell.open (); return this; } private TreeGpfTest run () { while (!shell.isDisposed ()) { if (!display.readAndDispatch ()) display.sleep (); } return this; } private void addComponents(Shell shell) { tree = new Tree(shell, SWT.NONE); tree.addTreeListener(this); initializeTreeItems(); GridData data = new GridData(); data.horizontalAlignment = GridData.FILL; data.verticalAlignment = GridData.FILL; data.grabExcessHorizontalSpace = true; data.grabExcessVerticalSpace = true; tree.setLayoutData(data); runTestButton = new Button(shell, SWT.PUSH); runTestButton.setText("Run test."); runTestButton.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { runSelectionTest(); runTestButton.setText("Test Successful."); } }); } private void initializeTreeItems() { root = TreeNode.createTree(treeDepth, childrenPerNode); Vector children = root.getChildren(); for (int i = 0; i < children.size(); i ++) { TreeNode next = (TreeNode) children.elementAt(i); TreeItem item = new TreeItem(tree, 0); item.setData(next); item.setText(next.getName()); if (next.getChildren().size() > 0) { TreeItem fakeItem = new TreeItem (item, SWT.NULL); fakeItem.setText(falseNodeText); } } } public void treeCollapsed(TreeEvent event) { } /** * */ public void treeExpanded(TreeEvent event) { TreeItem item = (TreeItem) event.item; // If the node hasn't been viewed yet it has a dummy node // to allows expansion. Remove the dummy treeItem then // populate the tree if (item.getItems ()[0].getText().equals(falseNodeText)) { // dispose of dummy items TreeItem [] items = item.getItems (); for (int i=0; i<items.length; i++) items [i].dispose (); // expand the tree item expandTree (item); } } } /************************************************************************************************************************* * * TreeNode class * *************************************************************************************************************************/ import java.util.*; public class TreeNode { Vector children = new Vector(); String nodeName; static public TreeNode createTree(int depth, int numChildren) { TreeNode rootNode = new TreeNode("Root"); if (depth > 0) { int childDepth = depth - 1; for (int i = 0; i < numChildren; i++) { TreeNode nextChild = TreeNode.createTree(childDepth, numChildren); nextChild.setName("Level " + depth + " child " + i); rootNode.addChild(nextChild); } } return rootNode; } public TreeNode(String name) { super(); setName(name); } public Vector getChildren() { return children; } public void addChild(TreeNode child) { children.addElement(child); } public String getName() { return nodeName; } public void setName(String name) { nodeName = name; } } SN (12/23/99 11:27:44 AM) Long is not a problem. Also JH says: >Yeah, as long as the path I want to expand/select isn't already >expanded. If you just bring up the window and hit the test >button it should GP every time. > SN (12/23/99 12:11:53 PM) Does not GP in VA/Java but throws a null pointer exception. SN (12/23/99 1:03:42 PM) Ok, I know what's happening but I don't understand the failure mode. The example code is selecting a node that's not visible. This causes the tree to expand to show the node. The application's expand callbacks delete the children and this deletes the node that the application is trying to select. I don't understand the GP or null pointer exception yet. SN (1/4/00 5:28:00 PM) I hacked a quick fix that avoided the null pointer exception and this GP'd after sending the expand callbacks in TVM_SELECTITEM. It looks like deleting the item that is about to be selected inside of an expand callback (that is sent because the tree must expand to show the item about to be selected) causes Windows it GP when it finally get's around to selecting the item. I have no idea how to work around this. McQ (27/11/2000 3:24:15 PM) - If this is not going to be fixed, this needs to be documented as a known limitation. SN to update javadoc
PRODUCT VERSION: 991208 Windows VM
This very complicated GP exists in Windows. I don't know how to work around it at this time. Marking WONTFIX.
SN to write the documentation that describes the case and include in the readme.
I believe bug 33834 could be a variant of this test case. We are testing a workaround for this bug 4434 (and we are trying to understand the scope under which this problem occurs). This should also provide a fix for bug 33834. With a recent version of SWT (>= Eclipse 2.1 RC1), the test case in this PR causes the following events. - within the expand callback, a tree item is disposed - SWT removes the tree item from the tree table. - TVM_DELETEITEM is called to destroy the OS tree item. The problem is that, for some reason, this TVM_DELETEITEM causes a TVN_ITEMEXPANDING resulting in another SWT.Expand event. At this stage, the OS considers the tree item to still be there (TVM_GETITEM etc return it), but it has already been removed from the SWT tree table. - this causes TreeItem.getItems() to possibly return an array with a null item, causing the NPE. (remember: we are all here still before returning from the call to TVM_DELETEITEM). One workaround is to detect that case by checking for a null item in Tree.wmNotify.TVN_ITEMEXPANDING and in TreeItem.getItems java.lang.NullPointerException at PR4434BIG.treeExpanded(PR4434BIG.java:103) at org.eclipse.swt.widgets.TypedListener.handleEvent (TypedListener.java:173) at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:77) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:836) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:861) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:845) at org.eclipse.swt.widgets.Tree.wmNotifyChild(Tree.java:1883) at org.eclipse.swt.widgets.Control.WM_NOTIFY(Control.java:3810) at org.eclipse.swt.widgets.Composite.WM_NOTIFY(Composite.java:638) at org.eclipse.swt.widgets.Control.windowProc(Control.java:2810) at org.eclipse.swt.widgets.Decorations.windowProc (Decorations.java:1225) at org.eclipse.swt.widgets.Display.windowProc(Display.java:2285) at org.eclipse.swt.internal.win32.OS.CallWindowProcW(Native Method) at org.eclipse.swt.internal.win32.OS.CallWindowProc(OS.java:1232) at org.eclipse.swt.widgets.Tree.callWindowProc(Tree.java:152) at org.eclipse.swt.widgets.Control.windowProc(Control.java:2839) at org.eclipse.swt.widgets.Display.windowProc(Display.java:2285) at org.eclipse.swt.internal.win32.OS.SendMessageW(Native Method) at org.eclipse.swt.internal.win32.OS.SendMessage(OS.java:1781) at org.eclipse.swt.widgets.Tree.destroyItem(Tree.java:337) at org.eclipse.swt.widgets.TreeItem.releaseChild(TreeItem.java:482) at org.eclipse.swt.widgets.Widget.dispose(Widget.java:367) at PR4434BIG.treeExpanded(PR4434BIG.java:107) at org.eclipse.swt.widgets.TypedListener.handleEvent (TypedListener.java:173) at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:77) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:836) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:861) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:845) at org.eclipse.swt.widgets.Tree.wmNotifyChild(Tree.java:1883) at org.eclipse.swt.widgets.Control.WM_NOTIFY(Control.java:3810) at org.eclipse.swt.widgets.Composite.WM_NOTIFY(Composite.java:638) at org.eclipse.swt.widgets.Control.windowProc(Control.java:2810) at org.eclipse.swt.widgets.Decorations.windowProc (Decorations.java:1225) at org.eclipse.swt.widgets.Display.windowProc(Display.java:2285) at org.eclipse.swt.internal.win32.OS.CallWindowProcW(Native Method) at org.eclipse.swt.internal.win32.OS.CallWindowProc(OS.java:1232) at org.eclipse.swt.widgets.Tree.callWindowProc(Tree.java:152) at org.eclipse.swt.widgets.Control.windowProc(Control.java:2839) at org.eclipse.swt.widgets.Display.windowProc(Display.java:2285) at org.eclipse.swt.internal.win32.OS.SendMessageW(Native Method) at org.eclipse.swt.internal.win32.OS.SendMessage(OS.java:1781) at org.eclipse.swt.widgets.Tree.setSelection(Tree.java:1013) at PR4434BIG$1.widgetSelected(PR4434BIG.java:60) at org.eclipse.swt.widgets.TypedListener.handleEvent (TypedListener.java:87) at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:77) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:836) at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:1779) at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:1487) at PR4434BIG.main(PR4434BIG.java:68) Exception in thread "main"
Created attachment 3920 [details] test case which was causing the stack trace
Created attachment 3921 [details] test case
Fixed released version v>20030307
Approved by Mike and Veronika for RC3.