Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    destroy vs markForDestroy

    I've been reviewing our use of destroy and replacing it with markForDestroy in most cases as per the Javadoc for Canvas.markForDestroy().

    However, I would like clarification on a couple scenarios as we are making changes in a number of places and wish to confirm before proceeding.

    1. In the example below where a Tab is being selected and populated with a new pane, is it proper to call markForDestroy() here or should we be destroying the old pane synchronously using destroy().

    Code:
    tab.addTabSelectedHandler(new TabSelectedHandler() {
        @Override
        public void onTabSelected(TabSelectedEvent event) {
    	Canvas newCanvas = createSomeNewCanvas();
            Canvas oldCanvas = tab.getPane();
            tab.setPane(newCanvas);
            if (oldCanvas != null) oldCanvas.markForDestroy();
        }
    });
    2. In the example below, where destroy() is being called on object, and that object uses a context Menu that also needs to be destroyed, should we be calling destroy() or markForDestroy().

    Code:
    @Override
    public void destroy() {
        super.destroy();
        if (ctxMenu != null) {
            ctxMenu.markForDestroy();
            ctxMenu = null;
        }
    }
    Thank you

    #2
    In both these cases you should be fine to use markForDestroy().

    markForDestroy() will perform the destroy() on a timeout, meaning it won't impact the performance of the thread of execution which calls it at all.

    The only cases where you really need to perform a synchronous destroy are when you have a code flow which would actually be confused by the destroy target still be present - either being drawn, being included in a widget hierarchy or being in global scope - when it synchronously executes after the widget has supposedly been destroyed.

    For example if you destroy a widget with a specific ID and then create a new widget with the same ID (in the same thread of execution) you'd probably want a synchronous destroy() so there was no collision of ID.

    In some cases you may also want to ensure a widget is disconnected from its parent or cleared from the DOM synchronously. In this case you could use a destroy() call to immediately clear, deparent and destroy the widget, but this isn't strictly necessary - you could also use either 'deparent()' or 'clear()' and then markForDestroy().


    Regards
    Isomorphic Software

    Comment


      #3
      Thank you for the informative update.

      Comment


        #4
        We got the following exception in IE11 (attached) today, which seems to be around destroy()ing. Does the exception give an indication about what is happening here?
        Thanks
        Attached Files

        Comment


          #5
          Looking for some pointers on how we can diagnose such exceptions in IE11. There are no visible issues in the other browsers we use (FF, Chrome, Safari), but IE11 seems to be problematic for us.

          14:36:13.964:TMR5:WARN:Log:ClassFactory.addGlobalID: ID:'isc_xxxx' for object '[Menu ID:isc_xxxx]' collides with ID of existing object '[Menu ID:isc_xxxx]'. The pre-existing widget will be destroyed.
          14:36:13.976:TMR5:WARN:Log:TypeError: Unable to get property 'last' of undefined or null reference
          Stack from error.stack:
          Class._getLastProto () @ xxxx/sc/modules/ISC_Core.js:274:148
          Class.Super () @ opswise/sc/xxxx/ISC_Core.js:265:112
          Menu.destroy () @ opswise/sc/xxxx/ISC_Grids.js:3015:56
          ClassFactory.addGlobalID () @ xxxx/sc/modules/ISC_Core.js:184:7
          Canvas.init () @ xxxx/sc/modules/ISC_Core.js:1706:1
          Class.completeCreation () @ xxxx/sc/modules/ISC_Core.js:316:1
          Class.create () @ xxxx/sc/modules/ISC_Core.js:210:1883
          aFb () @ xxxx/F5EBFFFD8E3B7EF0BE9D95F9374E1277.cache.html:6219:4166
          Jwb () @ xxxx/F5EBFFFD8E3B7EF0BE9D95F9374E1277.cache.html:5875:340
          UEb () @ xxxx/F5EBFFFD8E3B7EF0BE9D95F9374E1277.cache.html:3275:47

          Any guidance would be much appreciated.

          Comment


            #6
            This part:
            14:36:13.964:TMR5:WARN:Log:ClassFactory.addGlobalID: ID:'isc_xxxx' for object '[Menu ID:isc_xxxx]' collides with ID of existing object '[Menu ID:isc_xxxx]'. The pre-existing widget will be destroyed.
            Is pretty clear - you are creating a Menu with a particular ID which matches the ID of another Menu which has already been created.
            This usually happens when you hardcode your IDs in your code and inadvertently run a piece of code twice (so you create a widget with some ID, and then create it again, withe same ID, causing the first version to be destroyed)-- or you simply use the same ID in 2 different pieces of code.

            In this case it's a little surprising as the ID looks like it might be autoGenerated (from the "isc_..." format), so there may be something else going on there.

            Regardless though we'd recommend you look at the code which actually creates the menu and determine whether you appear to be legitimately attempting to create this object with some ID while version with the same ID already exists on the page.

            The subsequent errors are hard to comment on in much depth without the context of the app - in short the "destroy" is somehow breaking things (probably knocking something out of scope which is expected to still be available to other app code) - but the fix is going to be determining why you're hitting this collision / auto-destroy in the first place.

            FYI - The fact that this is specific to IE is probably related to a native difference in event timings on the browsers. In IE (for example) focus events are fired asynchronously whereas they are synchronous for other browsers - and in some cases SmartClient framework code will behave differently in IE in order to workaround such differences.

            We'd recommend you isolate the code which creates the Menu and try to figure out why there is an ID collision. If you're unable to see anything which looks like an application coding error, perhaps assemble a small test case which simply creates the minimal UI required to trip the bug (two menus for example) and we can take a look at that.

            Regards
            Isomorphic Software

            Comment


              #7
              Hi, I am very much interested in how is the second part of the error possible.
              We get this error in our application (ONLY IN IE11). I think that IE11 is full of s*** and it is maybe something connected to the garbage collector there.

              In our case the same error is reported inside languages/Class.js.
              This is the method that fails:
              Code:
                  _getLastProto : function (methodName, obj) {
                      var superCalls = obj._superCalls,
                          protoList = superCalls == null ? null : superCalls[methodName];
              
                      //this.logWarn("for method: " + methodName + " chain is: " + protoList);
              
                      if (isc.isAn.Array(protoList)) return protoList.last();
                      return protoList;
                  },
              The error is:
              Code:
              "Unable to get property 'last' of undefined or null reference"
              And it is reported to be on this line:
              Code:
              if (isc.isAn.Array(protoList)) return protoList.last();
              Now, I am probably crazy, but protoList is either an array (so it has "last()"), or not! How is this even possible? isc.isAn.Array(null) and isc.isAn.Array(undefined) are both "FALSE".
              Yes, I am losing my mind. I need this weekend.

              Comment


                #8
                Unfortunately, we have not been able to isolate the problem.

                We use auto-generated IDs, we do not set them.

                Furthermore, while the example warning I provided referred to a Menu, the issue is not isolated to Menus.

                Regards

                Comment


                  #9
                  I will add that we also see the specific error "Unable to get property 'last' of undefined or null reference" in IE11.

                  Comment


                    #10
                    We really will need a way to reproduce this issue before we can tell what's going on here. As we noted, the error basically indicates ID collisions, but that should pretty much never happen for auto-assigned IDs unless there's some subtle usage issue.

                    Hard to comment on the warning about being unable to call 'last' on a null object, except to agree that it is confusing since the isAn.Array(...) check exists.
                    It seems quite likely that this is a result of the first problem in some way - the system is possibly attempting to destroy a widget at an invalid time or something similar, and subsequent code in the same thread is going haywire. Or it could be a GWT-specific issue we haven't seen - some GWT / JSNI oddity around object handling and scope which is somehow tripping you up. Really we'll need a way to reproduce so we can debug the issue on our end.

                    If you can come up with a small test case, which we can run on our end and which demonstrates the problem, we will probably be able to get to the bottom of it relatively quickly.

                    Regards
                    Isomorphic Software

                    Comment


                      #11
                      Originally posted by Isomorphic View Post
                      If you can come up with a small test case, which we can run on our end and which demonstrates the problem, we will probably be able to get to the bottom of it relatively quickly.
                      Thanks for writing. Unfortunately we've been trying to do this the past two weeks, but with absolutely NO luck. The application locks sometimes, under absolutely different circumstances - we've seen it after long idle period or under heavy use; when sorting a grid or when closing a modal window ...

                      At this point we believe we've missused markForDestroy() somewhere and IE11's garbage collector (an external process) is somehow messing references to objects in the UI thread. There is nothing else that I can think of explaining the {if(isArray) - undefined or null} ... not that this explanation is believeable.
                      Last edited by ispasov; 10th Oct 2014, 13:40.

                      Comment


                        #12
                        To everyone concerned - this seems to be our issue:

                        http://forums.smartclient.com/showthread.php?t=30683

                        I am looking forward to seeing some confirmation from Microsoft!

                        Comment

                        Working...
                        X