Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 482608

Summary: GridItems can get registered twice in ObjectRegistry leading to crash on destruction
Product: [RT] RAP Reporter: Wolfgang Pedot <wolfgang.pedot>
Component: RWTAssignee: Project Inbox <rap-inbox>
Status: RESOLVED FIXED QA Contact:
Severity: normal    
Priority: P3 CC: ivan
Version: 3.1   
Target Milestone: 3.1 M4   
Hardware: PC   
OS: Windows 7   
Whiteboard:
Attachments:
Description Flags
Patch for RAP-Demo to reproduce issue none

Description Wolfgang Pedot CLA 2015-11-19 11:51:24 EST
I stumbled upon another javascript-error while testing with out application (based on RAP 3.1M2): There is a virtual TableViewer with filters, now if I toggle a filter-relevant property of the currently selected element fast enough (clicking a checkbox in a PropertySheetPage actually) I can get the client to crash telling me that "destroy" on "rwt.widgets.GridItem" has failed because "this._children" is null.

Appearantly _getCachedChildren and _getUncachedChildren got called after the item itself had been destroyed causing the null-access. 
Further investigation then showed that one GridItem can actually get registered twice under two different _rwtIds in rwt.remote.ObjectFactory and thats the reason it gets destroyed twice.

I dont fully understand how that can happen, all I know is that I get calls to rwt.remote.ObjectRegistry.add with an object that already has a member "_rwtId" and that member is different from the id-parameter given to "add". The new id appears to always be the old id + 1. Once those "two" objects get destroyed the client crashes.

I have "fixed" this by adding null-checks to GridItem._getCachedChildren and _getUncachedChildren and returning an emtpy array but this does not strike me as an optimal solution.

Any pointers where to look further?
Comment 1 Wolfgang Pedot CLA 2015-11-19 14:03:58 EST
Some additional information:
If I click the checkbox that makes the item filtered rapidly (hide and show again), this is what happens:

--- New GridItem gets created for index 2735 and registered in ObjectRegistry
--- I added a random-field to track the instances
GridItem.createItem: [object rwt.widgets.Grid], 2735
new! 0.5655986634083092

--- Right afterwards a second create-operation is handled for the same index
--- so there is no new instance but the existing is returned
GridItem.createItem: [object rwt.widgets.Grid], 2735
caching! 0.5655986634083092  <-- same random as above

--- and now it gets registered twice (w3033 before, 3034 now)
Object TreeItem  registered twice! (w3033 and w3034)

--- next the old w3033 gets destroyed
Destroy w3033
random: 0.5655986634083092
Grid.getCachedChildren 0.5655986634083092
Grid.getUnCachedChildren 0.5655986634083092
GridItem.destruct 0.5655986634083092

--- now if I hide the element again this happens:

Destroy w3034
random: 0.5655986634083092
Grid.getCachedChildren 0.5655986634083092
Grid.getUnCachedChildren 0.5655986634083092

Note that there is no actual second call to "desctruct" on the 0.5655... instance but there are calls to getCached/UnCachedChildren and those would fail without my null-check
Comment 2 Wolfgang Pedot CLA 2015-11-20 03:29:27 EST
The item that gets registered twice appears to always be the last one in the table and it is also not working correctly afterwards because it is disposed already. It just shows the "..." you see when scrolling in a virtual table and items are being loaded but it is clickable and provides the proper selection.

It is very hard to produce the problem when the table is scolled down to the end, it is quite easy on top.
Comment 3 Ivan Furnadjiev CLA 2015-11-20 03:31:41 EST
This is an interesting finding. Could you please create a self-running snippet that demostrate the issue? We will ivestigate it as soon as we have a reproducible scenario.
Comment 4 Wolfgang Pedot CLA 2015-11-20 04:56:23 EST
I will look into that, but it may take some time

It looks like an order-issue of some sort, I can see that the new TableItem gets created before the old one is disposed and those commands appear to reach the client in one response. If I am slow enough and the commands are delivered in separate responses dispose happens before create and everything is fine.

This is also visible on the java-side, one potential fix could be to move the call to "diposeWidgets" above the call to "renderShells" in DisplayLCA.render but I have no Idea what side-effects that might have....
Comment 5 Wolfgang Pedot CLA 2015-11-20 12:32:19 EST
I finally found the root cause (I think): it all boils down to refreshing the TableViewer twice in one Display.syncExec Runnable. What I was triggering in our application was two change-events which were consolidated into one Runnable and caused two refreshes because the item should be hidden and then shown again.

I patched the demo accordingly and managed to reproduce the issue there. The patch I attached is very crude but it gets the job done. It is important that the table has a selection or the problem wont occur so you need to click an item each time the selection disappears (every 2 sec). After a few clicks the client should crash.

Enabling hashLookups on the TableViewer also makes the issue go away because there are no more TableItems created or destroyed.
Comment 6 Wolfgang Pedot CLA 2015-11-20 12:33:41 EST
Created attachment 258186 [details]
Patch for RAP-Demo to reproduce issue
Comment 7 Ivan Furnadjiev CLA 2015-11-23 08:02:08 EST
(In reply to comment #4)
> This is also visible on the java-side, one potential fix could be to move the
> call to "diposeWidgets" above the call to "renderShells" in DisplayLCA.render
> but I have no Idea what side-effects that might have....
Wolfgang, with change https://git.eclipse.org/r/#/c/60461/ we restored the previouse order (like in RAP 3.0) of "diposeWidgets" and "renderShells" in DisplayLCA.render. Could you please check if the issue is still reproducible with RAP nightly [1]?

[1] p2 repo: http://download.eclipse.org/rt/rap/nightly/runtime/
Comment 8 Ivan Furnadjiev CLA 2015-11-23 08:14:35 EST
I'll close it as fixed with change https://git.eclipse.org/r/#/c/60461/. Please reopen if you can reproduce it with RAP nigntly.
Comment 9 Wolfgang Pedot CLA 2015-11-23 09:06:33 EST
Will do.

BTW: the changed order in 3.1M2 also breaks tables with an ObservableListContentProvider. If an item is moved up or down in the list it gets rendered twice on the client-side and the client crashes reproducibly when the table gets disposed. Changing the order back fixes this, will test with the nightly as well, I see no need for a bugreport if its fixed already.
Comment 10 Ivan Furnadjiev CLA 2015-11-23 09:09:52 EST
We also have plans to backport this change to 3.1 SR2, as it's broken there too - https://git.eclipse.org/r/#/c/60509/
Comment 11 Wolfgang Pedot CLA 2015-11-23 09:48:18 EST
Looks good with current git, both issues seem to be fixed.
Comment 12 Ivan Furnadjiev CLA 2015-11-23 10:02:11 EST
(In reply to Wolfgang Pedot from comment #11)
> Looks good with current git, both issues seem to be fixed.

Great. Thanks for verifying it.