{ "id": "63193", "key": "TIMOB-2561", "fields": { "issuetype": { "id": "1", "description": "A problem which impairs or prevents the functions of the product.", "name": "Bug", "subtask": false }, "project": { "id": "10153", "key": "TIMOB", "name": "Titanium SDK/CLI", "projectCategory": { "id": "10100", "description": "Titanium and related SDKs used in application development", "name": "Client" } }, "fixVersions": [ { "id": "11244", "name": "Release 1.7.0", "archived": true, "released": true, "releaseDate": "2011-06-13" }, { "id": "11245", "name": "Sprint 2011-10", "archived": true, "released": true, "releaseDate": "2011-03-14" } ], "resolution": { "id": "7", "description": "", "name": "Invalid" }, "resolutiondate": "2011-04-26T09:04:11.000+0000", "created": "2011-04-15T03:22:49.000+0000", "priority": { "name": "Trivial", "id": "5" }, "labels": [ "android", "defect", "enterprise", "httpclient", "release-1.7.0", "rplist" ], "versions": [], "issuelinks": [], "assignee": { "name": "dthorp", "key": "dthorp", "displayName": "Don Thorp", "active": true, "timeZone": "America/Los_Angeles" }, "updated": "2011-12-23T08:52:01.000+0000", "status": { "description": "The issue is considered finished, the resolution is correct. Issues which are closed can be reopened.", "name": "Closed", "id": "6", "statusCategory": { "id": 3, "key": "done", "colorName": "green", "name": "Done" } }, "components": [ { "id": "10202", "name": "Android", "description": "Android Platform" } ], "description": "{html}

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

\n

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

\n
\nat android.os.MessageQueue.enqueueMessage(MessageQueue.java:179)\nat android.os.Handler.sendMessageAtTime(Handler.java:457)\nat android.os.Handler.sendMessageDelayed(Handler.java:430)\nat android.os.Handler.post(Handler.java:248)\nat org.appcelerator.titanium.kroll.KrollContext.post(KrollContext.java:123)\nat org.appcelerator.titanium.kroll.KrollCallback.callAsync(KrollCallback.java:154)\nat org.appcelerator.titanium.kroll.KrollCallback.callAsync(KrollCallback.java:89)\nat org.appcelerator.titanium.kroll.KrollCallback.callAsync(KrollCallback.java:84)\nat ti.modules.titanium.network.TiHTTPClient.fireCallback(TiHTTPClient.java:468)\nat ti.modules.titanium.network.TiHTTPClient.fireCallback(TiHTTPClient.java:459)\nat ti.modules.titanium.network.TiHTTPClient.setReadyState(TiHTTPClient.java:491)\nat ti.modules.titanium.network.TiHTTPClient$ClientRunnable.run(TiHTTPClient.java:989)\nat java.lang.Thread.run(Thread.java:1096)\n
{html}", "attachment": [], "flagged": false, "summary": "Network error when invoking a Http request multiple times", "creator": { "name": "rgyani", "key": "rgyani", "displayName": "rGyani", "active": true, "timeZone": "America/Los_Angeles" }, "subtasks": [], "reporter": { "name": "rgyani", "key": "rgyani", "displayName": "rGyani", "active": true, "timeZone": "America/Los_Angeles" }, "environment": null, "comment": { "comments": [ { "id": "128779", "author": { "name": "rgyani", "key": "rgyani", "displayName": "rGyani", "active": true, "timeZone": "America/Los_Angeles" }, "body": "{html}

Some more info:

\n

this happens when I have something like this

\n

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

\n
\n{\n             loadBoardsFromNetwork(); // it fails in this function\n});\nfrmNewBoard.open(\n{\n});\n
\n

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

\n

Thanks

{html}", "updateAuthor": { "name": "rgyani", "key": "rgyani", "displayName": "rGyani", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2011-04-15T03:22:49.000+0000", "updated": "2011-04-15T03:22:49.000+0000" }, { "id": "128780", "author": { "name": "rgyani", "key": "rgyani", "displayName": "rGyani", "active": true, "timeZone": "America/Los_Angeles" }, "body": "{html}

Is someone even listening to this thread to help identify the\nissue?

\n

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

\n

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

\n
\n         loadBoardsFromNetwork(); // it fails in this function\n
\n

}); frmNewBoard.open(
\n{ });

\n

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

\n

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

\n
\n         loadBoardsFromNetwork(); // works now\n
\n

});

\n

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

\n

So obviously, there is some threading issue with 'close'\nevent

{html}", "updateAuthor": { "name": "rgyani", "key": "rgyani", "displayName": "rGyani", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2011-04-15T03:22:49.000+0000", "updated": "2011-04-15T03:22:49.000+0000" }, { "id": "128781", "author": { "name": "taazza", "key": "taazza", "displayName": "Taazza", "active": true, "timeZone": "America/Los_Angeles" }, "body": "{html}

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

\n

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

{html}", "updateAuthor": { "name": "taazza", "key": "taazza", "displayName": "Taazza", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2011-04-15T03:22:50.000+0000", "updated": "2011-04-15T03:22:50.000+0000" }, { "id": "128782", "author": { "name": "opiecyrus", "key": "opiecyrus", "displayName": "Opie Cyrus", "active": true, "timeZone": "America/Chicago" }, "body": "{html}

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

\n

Thanks
\nOpie

{html}", "updateAuthor": { "name": "opiecyrus", "key": "opiecyrus", "displayName": "Opie Cyrus", "active": true, "timeZone": "America/Chicago" }, "created": "2011-04-15T03:22:50.000+0000", "updated": "2011-04-15T03:22:50.000+0000" }, { "id": "128783", "author": { "name": "davidhoare", "key": "davidhoare", "displayName": "davidhoare", "active": true, "timeZone": "America/Los_Angeles" }, "body": "{html}

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

{html}", "updateAuthor": { "name": "davidhoare", "key": "davidhoare", "displayName": "davidhoare", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2011-04-15T03:22:50.000+0000", "updated": "2011-04-15T03:22:50.000+0000" }, { "id": "128784", "author": { "name": "dtoth", "key": "dtoth", "displayName": "Dawson Toth", "active": true, "timeZone": "America/New_York" }, "body": "{html}

Sample Code

\n

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

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

Resulting Trace Level Log

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

Tested On

\n

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

\n

Associated Helpdesk Ticket

\n

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

{html}", "updateAuthor": { "name": "dtoth", "key": "dtoth", "displayName": "Dawson Toth", "active": true, "timeZone": "America/New_York" }, "created": "2011-04-15T03:22:51.000+0000", "updated": "2011-04-15T03:22:51.000+0000" }, { "id": "128785", "author": { "name": "andreassandberg", "key": "andreassandberg", "displayName": "Andreas sandberg", "active": true, "timeZone": "America/Los_Angeles" }, "body": "{html}

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

{html}", "updateAuthor": { "name": "andreassandberg", "key": "andreassandberg", "displayName": "Andreas sandberg", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2011-04-15T03:22:51.000+0000", "updated": "2011-04-15T03:22:51.000+0000" }, { "id": "128786", "author": { "name": "opiecyrus", "key": "opiecyrus", "displayName": "Opie Cyrus", "active": true, "timeZone": "America/Chicago" }, "body": "{html}

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

\n

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

\n
\nvar tabGroup = Titanium.UI.createTabGroup();\nvar win = Ti.UI.createWindow();\nvar tab = Titanium.UI.createTab({ title:'HTTP Exception Reproducer', window:win });\ntabGroup.addTab(tab);\ntabGroup.open();\n\nvar detailWin = Ti.UI.createWindow();\nvar xhr = Ti.Network.createHTTPClient({'timeout' : 25000});\nxhr.onload = function() {\n    var db = Ti.UI.createButton({ width:250, height:100, title:'Now Touch Me.'});\n    db.addEventListener('click', function() {\n        var dialog = Titanium.UI.createOptionDialog({\n            options:['Do It'],\n            title:'Finally, touch \"Do It\".'\n        });\n        dialog.addEventListener('click', function() {\n            var xhr = Ti.Network.createHTTPClient({'timeout' : 25000});\n            xhr.onload = function() {\n                var xhr = Ti.Network.createHTTPClient({'timeout' : 25000});\n                xhr.onload = function() {\n                     Ti.API.info(\"closing window\");\n                     detailWin.close();\n                };\n                xhr.open('POST', 'http://a17g.com');\n                xhr.send({'method':'get_entry_list', 'input_type':'JSON','response_type':'JSON','rest_data':'asdf'});\n            };\n            xhr.open('POST', 'http://a17g.com');\n            xhr.send();\n        });\n        dialog.show();\n    });\n    detailWin.add(db);\n    tab.open(detailWin);\n};\nxhr.open('POST', 'http://a17g.com');\nxhr.send();\n
{html}", "updateAuthor": { "name": "opiecyrus", "key": "opiecyrus", "displayName": "Opie Cyrus", "active": true, "timeZone": "America/Chicago" }, "created": "2011-04-15T03:22:53.000+0000", "updated": "2011-04-15T03:22:53.000+0000" }, { "id": "128787", "author": { "name": "andreassandberg", "key": "andreassandberg", "displayName": "Andreas sandberg", "active": true, "timeZone": "America/Los_Angeles" }, "body": "{html}

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

{html}", "updateAuthor": { "name": "andreassandberg", "key": "andreassandberg", "displayName": "Andreas sandberg", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2011-04-15T03:22:53.000+0000", "updated": "2011-04-15T03:22:53.000+0000" }, { "id": "177121", "author": { "name": "ziggythehamster", "key": "ziggythehamster", "displayName": "Keith Gable", "active": true, "timeZone": "America/Los_Angeles" }, "body": "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.", "updateAuthor": { "name": "ziggythehamster", "key": "ziggythehamster", "displayName": "Keith Gable", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2011-12-23T08:52:01.000+0000", "updated": "2011-12-23T08:52:01.000+0000" } ], "maxResults": 10, "total": 10, "startAt": 0 } } }