9 Replies Latest reply on Jan 9, 2007 11:17 AM by Citnam

    [Unload SWF] appears in console and hangs app

    Citnam
      Occasionally, "[Unload SWF] path:main-debug.swf" appears and kills any HTTPService calls that are made.

      The app behaves as such:

      1. About 4 HTTPService calls are made at once, using different HTTPService instances.
      2. Occasionally, in the debug console a "[Unload SWF]..." appears, showing the path to my app. Sometimes it appears once for every webservice call that I make.
      3. Each webservice that gets the "[Unload SWF]" will never return and hangs forever.

      Sometimes, I'll also see a "[SWF] path:main-debug.swf" message in the console, at which point the webservices will hang again. If I click "Cancel" in my app, then try it again, they will sometimes magically work (and I don't get those [Unload SWF] messages).

      Any help would be greatly appreciated!

      -Michael Whitaker:confused;
        • 1. Re: [Unload SWF] appears in console and hangs app
          mike_morearty Level 1
          Hmm, I've never seen this. I can tell you that [Unload SWF] means that the Flash player has told the debugger that it thinks the SWF has been unloaded from memory. Doesn't make any sense for that to happen in the scenario you are describing, unless there is additional code (beyond what you have described) that is unloading SWFs.

          Any chance you could post sample code?
          • 2. Re: [Unload SWF] appears in console and hangs app
            Citnam Level 1
            Unfortunately, I can't supply any source code. The project is both large and confidential.

            If [Unload SWF] is displayed when the Flash player has told the debugger that a swf is unloaded, then I'm confused about why the Flash player constantly tells the debugger that my main app is being unloaded. It makes sense when I unload an embedded swf, or an external one from my application, but to have the player tell the debugger that my application has unloaded, while I'm still using it, baffles me.

            I first thought, and perhaps still do, that it was some sort of HTTPService bug. But I haven't had the time recently to verify that. In my entire app, I am only using a SWFLoader to load/unload a seperate swf in only one location. I'll do some testing to see if those messages aren't being sent by that instance.

            What conditions apply in order for the Flash player to think a SWF is unloaded?

            Thanks for your help,

            Michael Whitaker
            MediaForge
            • 3. Re: [Unload SWF] appears in console and hangs app
              mike_morearty Level 1
              I'm not an expert on exactly what causes the player to think a swf has been unloaded, but basically, it is the kind of stuff you would expect, and has nothing at all to do with HTTPService (as far as I know). One tricky case is that since the player uses garbage collection, I think it possible for the player to send a swf-unloaded message to the debugger at a later time than you would have thought -- when the garbage collector runs, then the player detects that the swf has no references to it. But this is hearsay -- I'm not sure if I'm right about that.

              And yes, it is very weird that you are being told that your main app is being unloaded. That doesn't make any sense at all to me.

              What player version are you using? If you are using 9,0,16,0, then please upgrade to 9,0,28,0. Release 28 did have some bug fixes that might conveivably be related to the problem you are seeing, although I'm not sure.
              • 4. [Unload SWF] appears in console and hangs app
                Citnam Level 1
                I'm currently using 9,0,18,xx (or similar). In looking for the latest debug version of the flash player for OSX, all I can find is a PPC version of 9.0.r28, not an Intel version. The installer for the PPC version won't continue once it detects I have an Intel chipset. Sooo, unless I install a non-debug version, I can't upgrade beyond 9,0,18. I guess they haven't posted the latest version of the flash debug player for OSX on an Intel chipset yet.

                About the app unloading itself (or reporting that it is): while I'm using our app, it will report that it is loading and unloading itself more than 5 times. Sometimes it will show the [Unload SWF] ...main-debug.swf 4 times in a row. Rather strange.

                So, moving on, if that isn't what's causing my app to hang, are there any bugs/issues relating with the HTTPService or otherwise that would cause the app to ignore the fact that a web service call has returned? I haven't found anything myself in the docs.

                This is the page I'm refering to about the Flash Debug Plug-in:
                Flash Debug Plug-in Download <Adobe.com>

                I'm looking at the "Download the Macintosh Flash Player 9 Plugin content debugger". It is a PPC download, not an Intel chipset download.
                • 5. Re: [Unload SWF] appears in console and hangs app
                  mike_morearty Level 1
                  It looks like finally, as of today with the release of Flex 2.0.1, there is a Mac Universal version of Flash Player 9.0r28. I just tried it myself -- downloaded Flex Builder 2.0.1 from http://www.adobe.com/cfusion/tdrc/index.cfm?loc=en_us&product=flex and installed it onto my Intel Mac. I don't know if there is a better place to get the Flash player other than having it as part of the Flex Builder install, but in any case getting it from the Flex Builder install worked.
                  • 6. Re: [Unload SWF] appears in console and hangs app
                    Citnam Level 1
                    Unbelievable...

                    I think I may have found the problem and solution:

                    The way I was using the HTTPService component was through a seperate class which itself contained the httpservice that I was instantiating and calling on a per-need basis. The function I was using to call my web service needs accepted two function pointers (or Function types) which were called on a ResultEvent or a FaultEvent (from the HTTPService). I was using lamba functions (inline functions) in the method call. That is what seemed to be the problem. As soon as I moved the lamba functions outside ,into real functions, and just passed their reference through my method, everything worked.

                    I've noticed several problems with lamba functions, all of which are very unfortunate (because I would use them more, but they are so buggy):

                    1. A lamba function sometimes has some weird scope. At times calling "this.something" fails from within the lamba function as 'this' is null. Ex:

                    class Bob
                    {
                    public Bob()
                    {
                    this.addEventListener(Event.ENTER_FRAME, function(e:Event):void { trace("this: " + this.toString()); }, false, 0, true);
                    }
                    }

                    (Note: this is 1% psudo code (uncompiled).) "this" will sometimes be null (depending on where the lamba is used).

                    2. If, using the above code, you were to instantiate several Bobs at a time, and add them to the displaylist, sometimes only ONE of the instances will actually call their lamba function on enterframe; the others won't. I'm not sure why this happens, but I think multiple instances of the same class using a lamba function tends to conflict in memory or something. (or in the special lamba-scope).

                    3. At times, as per my problem in this thread, a lamba function won't even be called. I've solved this by pulling out the lamba functions and placing them in real functions, then just passing the pointer across.

                    I guess the debugger sending [Unload SWF] and [SWF] messages were just a coincidence (unless they somehow affect lamba functions). I'm going to continue testing this to verify that the problem has gone away. If it hasn't, I'll probably start a new thread.

                    Thanks for your help mike_morearty!
                    • 7. Re: [Unload SWF] appears in console and hangs app
                      mike_morearty Level 1
                      Glad you found it.

                      #1 is not a bug -- it is an unfortunate characteristic of ECMAScript, and therefore of ActionScript. When you call a lambda function, if you do not explicitly specify a "this" object by passing it as the first argument of Function.call() or Function.apply(), then the function uses the "global" object as its "this" pointer. And for lambda functions, "this" is of type Object -- that is, it can be any type at all, no matter where what class your function is defined in.

                      When you pull the function up to be a top-level function of the class, then it is more like C++ or Java: Its "this" is of the type specified by the enclosing class, and you can only call it if you already have a pointer to that type.

                      In your example, if you need the lamba function to have access to the original "this", you can write it like this:

                      class Bob
                      {
                      public Bob()
                      {
                      var self:Bob = this;
                      this.addEventListener(Event.ENTER_FRAME, function(e:Event):void { trace("this: " + self.toString()); }, false, 0, true);
                      }
                      }

                      The local "self" is on the scope chain of the lambda function, so the lambda function can refer to it.

                      Here's another quirk: Even though the "this" of the lambda function might be any old thing, the parent class's "this" object IS on the scope chain, and its members CAN be referred to by name -- just not with "this"!! For example, say Bob has a field myField:

                      class Bob
                      {
                      public var myField:String = "this is myfield";

                      public Bob()
                      {
                      this.addEventListener(Event.ENTER_FRAME, function(e:Event):void
                      {
                      trace("this.myField: " + this.myField); // will probably fail
                      trace("myField: " + myField); // will work!
                      }
                      , false, 0, true);
                      }
                      }

                      Coming from a C++ background, I found it incredibly counterintuitive that "this.myField" would fail and "myField" would work. I am used to it now, but I still don't like it.

                      Someday I want to write up some info about the scopechain as a posting on my blog...

                      As for your #2 and #3, hmm, I haven't seen those problems. I'll do a few experiments to see if I can reproduce them.
                      • 8. Re: [Unload SWF] appears in console and hangs app
                        mike_morearty Level 1
                        Actually, I just realized something critically important about your example, which is probably causing the problems: You passed "true" as the 5th parameter of addEventListener(), the useWeakReference parameter.

                        You must never pass "true" if the listener is a lambda function. When the listener is a lambda function, the function itself is a garbage-collectable object. The way you wrote your code, the *only* reference to that function is the listener. But since you passed useWeakReference=true, the listener is *not* holding a reference to that lambda as far as the garbage collector is concerned, so there are *no* references to it. So, at some random time as your program runs, the lambda function gets collected, and thus does not get called!

                        This is not a bug. If you want the listener to be a lambda function, leave useWeakReference as false (the default). I'll suggest to the documentation team that they mention this in the docs for addEventListener.
                        • 9. Re: [Unload SWF] appears in console and hangs app
                          Citnam Level 1
                          Hey, thanks for your input!

                          I'm glad I understand now what went wrong. By habit, I use weak references on event listeners. I picked this up from some blog I read about security and memory efficiency by using weak references, but never anticipated its effect on lambda functions.

                          I think my co-worker had another issue about lambda functions, but that's for another day.

                          Thanks again!