[TIMOB-2561] Network error when invoking a Http request multiple times
GitHub Issue | n/a |
---|---|
Type | Bug |
Priority | Trivial |
Status | Closed |
Resolution | Invalid |
Resolution Date | 2011-04-26T09:04:11.000+0000 |
Affected Version/s | n/a |
Fix Version/s | Release 1.7.0, Sprint 2011-10 |
Components | Android |
Labels | android, defect, enterprise, httpclient, release-1.7.0, rplist |
Reporter | rGyani |
Assignee | Don Thorp |
Created | 2011-04-15T03:22:49.000+0000 |
Updated | 2011-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
- 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
- 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' eventfrmNewBoard.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
- 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.
- Opie Cyrus 2011-04-15
Can you please include a boiled down test app that we can use to reproduce the behavior?
Thanks
Opie - 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 - 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.2Associated Helpdesk Ticket
http://developer.appcelerator.com/helpdesk/view/65211">http://developer.appcelerator.com/helpdesk/view/65211
- 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!
- 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();
- 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.
- 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.