Titanium JIRA Archive
Titanium SDK/CLI (TIMOB)

[TIMOB-2561] Network error when invoking a Http request multiple times

GitHub Issuen/a
TypeBug
PriorityTrivial
StatusClosed
ResolutionInvalid
Resolution Date2011-04-26T09:04:11.000+0000
Affected Version/sn/a
Fix Version/sRelease 1.7.0, Sprint 2011-10
ComponentsAndroid
Labelsandroid, defect, enterprise, httpclient, release-1.7.0, rplist
ReporterrGyani
AssigneeDon Thorp
Created2011-04-15T03:22:49.000+0000
Updated2011-12-23T08:52:01.000+0000

Description

I am getting the following error when a function calling a Ti.Network.createHTTPClient() -> send() is invoked a second time. First time it works well and good

WARN/MessageQueue(367): Handler{43f82b30} sending message to a Handler on a dead thread
java.lang.RuntimeException: Handler{43f82b30} sending message to a Handler on a dead thread

at android.os.MessageQueue.enqueueMessage(MessageQueue.java:179)
at android.os.Handler.sendMessageAtTime(Handler.java:457)
at android.os.Handler.sendMessageDelayed(Handler.java:430)
at android.os.Handler.post(Handler.java:248)
at org.appcelerator.titanium.kroll.KrollContext.post(KrollContext.java:123)
at org.appcelerator.titanium.kroll.KrollCallback.callAsync(KrollCallback.java:154)
at org.appcelerator.titanium.kroll.KrollCallback.callAsync(KrollCallback.java:89)
at org.appcelerator.titanium.kroll.KrollCallback.callAsync(KrollCallback.java:84)
at ti.modules.titanium.network.TiHTTPClient.fireCallback(TiHTTPClient.java:468)
at ti.modules.titanium.network.TiHTTPClient.fireCallback(TiHTTPClient.java:459)
at ti.modules.titanium.network.TiHTTPClient.setReadyState(TiHTTPClient.java:491)
at ti.modules.titanium.network.TiHTTPClient$ClientRunnable.run(TiHTTPClient.java:989)
at java.lang.Thread.run(Thread.java:1096)

Comments

  1. rGyani 2011-04-15

    Some more info:

    this happens when I have something like this

    frmNewBoard.addEventListener('close', function(e)

       {
                    loadBoardsFromNetwork(); // it fails in this function
       });
       frmNewBoard.open(
       {
       });
       

    i.e. the network request works fine when a Window is loaded, the window then loads another window frmNewBoard on a button click. I have added an event to listen for frmBewBoard closing, and calling the network request. The error message above is what i get when this second network request is sent.

    Thanks

  2. rGyani 2011-04-15

    Is someone even listening to this thread to help identify the issue?

    Anyhow, I have some further info.
    This problem only occurs when the network request is called from 'close' event

    frmNewBoard.addEventListener('close', function(e)
    {

                loadBoardsFromNetwork(); // it fails in this function
       

    }); frmNewBoard.open(
    { });

    However it works if I call a button click event which load the board like this

    button.addEventListener('close', function(e)
    {

                loadBoardsFromNetwork(); // works now
       

    });

    frmNewBoard.addEventListener('close', function(e)
    { button.fireEvent('click');// it works now }); frmNewBoard.open(
    { });

    So obviously, there is some threading issue with 'close' event

  3. Taazza 2011-04-15

    We are facing exactly the same problem after upgrading to 1.5.0 on Android. We add an event listener for the 'close' event on a window. In the event handler, we make a network call which is failing with the same exception. This used to work fine on 1.4.x.

    We will try out Ravi's workaround in the meanwhile and update this ticket with our results. Thanks Ravi.

  4. Opie Cyrus 2011-04-15

    Can you please include a boiled down test app that we can use to reproduce the behavior?

    Thanks
    Opie

  5. davidhoare 2011-04-15

    seems to be related to whether you open the window as modal or not, then drop back to the main window. When I tried it with a modal window, the returning 'close' event and subsequent xhr request did not work. When I switched it to a normal window, it DID work - the rest of the code being the same in either case.
    go figure!
    David

  6. Dawson Toth 2011-04-15

    Sample Code

    I was able to reproduce the same error using the following code. Note that it's a very sensitive bit of code... if you remove pretty much anything from the source below, the exception won't get hit. It was rather excruciating to recreate, actually.

       var tabGroup = Titanium.UI.createTabGroup();
       var win = Ti.UI.createWindow();
       var tab = Titanium.UI.createTab({ title:'HTTP Exception Reproducer', window:win });
       tabGroup.addTab(tab);
       tabGroup.open();
       
       var detailWin = Ti.UI.createWindow();
       var xhr = Ti.Network.createHTTPClient({'timeout' : 25000});
       xhr.onload = function() {
           var db = Ti.UI.createButton({ width:250, height:100, title:'Now Touch Me.'});
           db.addEventListener('click', function() {
               var dialog = Titanium.UI.createOptionDialog({
                   options:['Do It'],
                   title:'Finally, touch "Do It".'
               });
               dialog.addEventListener('click', function() {
                   var xhr = Ti.Network.createHTTPClient({'timeout' : 25000});
                   xhr.onload = function() {
                       var xhr = Ti.Network.createHTTPClient({'timeout' : 25000});
                       xhr.onload = function() {
                       };
                       xhr.open('POST', 'http://a17g.com');
                       xhr.send({'method':'get_entry_list', 'input_type':'JSON','response_type':'JSON','rest_data':'asdf'});
                       detailWin.close();
                   };
                   xhr.open('POST', 'http://a17g.com');
                   xhr.send();
               });
               dialog.show();
           });
           detailWin.add(db);
           tab.open(detailWin);
       };
       xhr.open('POST', 'http://a17g.com');
       xhr.send();
       

    Resulting Trace Level Log

       [TRACE] D/TiHttpClient( 801): (TiHttpClient-3) [451,41308] Setting ready state to 2
       [TRACE] D/TiHttpClient( 801): (TiHttpClient-3) [1,41309] Setting ready state to 3
       [TRACE] D/TiHttpClient( 801): (TiHttpClient-3) [85,41394] Setting ready state to 4
       [TRACE] W/MessageQueue( 801): Handler{45055658} sending message to a Handler on a dead thread
       [TRACE] W/MessageQueue( 801): java.lang.RuntimeException: Handler{45055658} sending message to a Handler on a dead thread
       [TRACE] W/MessageQueue( 801): at android.os.MessageQueue.enqueueMessage(MessageQueue.java:179)
       [TRACE] W/MessageQueue( 801): at android.os.Handler.sendMessageAtTime(Handler.java:457)
       [TRACE] W/MessageQueue( 801): at android.os.Handler.sendMessageDelayed(Handler.java:430)
       [TRACE] W/MessageQueue( 801): at android.os.Handler.post(Handler.java:248)
       [TRACE] W/MessageQueue( 801): at org.appcelerator.titanium.kroll.KrollContext.post(KrollContext.java:125)
       [TRACE] W/MessageQueue( 801): at org.appcelerator.titanium.kroll.KrollCallback.callAsync(KrollCallback.java:161)
       [TRACE] W/MessageQueue( 801): at org.appcelerator.titanium.kroll.KrollCallback.callAsync(KrollCallback.java:96)
       [TRACE] W/MessageQueue( 801): at org.appcelerator.titanium.kroll.KrollCallback.callAsync(KrollCallback.java:91)
       [TRACE] W/MessageQueue( 801): at ti.modules.titanium.network.TiHTTPClient.fireCallback(TiHTTPClient.java:477)
       [TRACE] W/MessageQueue( 801): at ti.modules.titanium.network.TiHTTPClient.fireCallback(TiHTTPClient.java:468)
       [TRACE] W/MessageQueue( 801): at ti.modules.titanium.network.TiHTTPClient.setReadyState(TiHTTPClient.java:500)
       [TRACE] W/MessageQueue( 801): at ti.modules.titanium.network.TiHTTPClient$ClientRunnable.run(TiHTTPClient.java:1017)
       [TRACE] W/MessageQueue( 801): at java.lang.Thread.run(Thread.java:1096)
       

    Tested On

    Titanium Mobile SDK 1.6.0 1/19/11 13:13
    Android Simulator 2.2

    Associated Helpdesk Ticket

    http://developer.appcelerator.com/helpdesk/view/65211">http://developer.appcelerator.com/helpdesk/view/65211

  7. Andreas sandberg 2011-04-15

    Any chance we can bump the priority of this up to high? It's causing our app to crash in numerous places. Thanks!

  8. Opie Cyrus 2011-04-15

    This behavior is actually due to the containing context for the httpclient object being destroyed before the request finishes executing. In the above example, the httpclient that contains the callbacks for the request is already destroyed before all the updates fire and thus an exception is generated. In short, there is a race condition between the send call and the close.

    In order to get around this, the close should be called from the onload callback for the request. In general, any operations that a re dependent on network requests should be event / callback driven since you can not relay on network requests happening in a timely fashion. I have provided a modified version of the previous example code.

       var tabGroup = Titanium.UI.createTabGroup();
       var win = Ti.UI.createWindow();
       var tab = Titanium.UI.createTab({ title:'HTTP Exception Reproducer', window:win });
       tabGroup.addTab(tab);
       tabGroup.open();
       
       var detailWin = Ti.UI.createWindow();
       var xhr = Ti.Network.createHTTPClient({'timeout' : 25000});
       xhr.onload = function() {
           var db = Ti.UI.createButton({ width:250, height:100, title:'Now Touch Me.'});
           db.addEventListener('click', function() {
               var dialog = Titanium.UI.createOptionDialog({
                   options:['Do It'],
                   title:'Finally, touch "Do It".'
               });
               dialog.addEventListener('click', function() {
                   var xhr = Ti.Network.createHTTPClient({'timeout' : 25000});
                   xhr.onload = function() {
                       var xhr = Ti.Network.createHTTPClient({'timeout' : 25000});
                       xhr.onload = function() {
                            Ti.API.info("closing window");
                            detailWin.close();
                       };
                       xhr.open('POST', 'http://a17g.com');
                       xhr.send({'method':'get_entry_list', 'input_type':'JSON','response_type':'JSON','rest_data':'asdf'});
                   };
                   xhr.open('POST', 'http://a17g.com');
                   xhr.send();
               });
               dialog.show();
           });
           detailWin.add(db);
           tab.open(detailWin);
       };
       xhr.open('POST', 'http://a17g.com');
       xhr.send();
       
  9. Andreas sandberg 2011-04-15

    Opie, thanks for looking into this, we have already re-worked our code base to incorporate the necessary changes. I guess my only comment is that the code referenced previously does work with the iphone implementation and as an end user I really shouldn't have to care about the implementation limitations for droid. The inconsistency between the platforms will probably end up biting some users trying to port their apps over.

  10. Keith Gable 2011-12-23

    I'm experiencing this on 1.7.6 (git commit 158a8923ca4d4b32b3934707419be49597ff9006) still. Except that I'm making HTTPClient requests before any window is shown, so closing the window isn't possible. I'm thinking that there's a Ti activity that isn't exposed to me that is being .finish()ed and the handler is being executed in that activity. I'm going to try wrapping my calls in a setTimeout to see if giving the activity time to die first solves it.

JSON Source