Titanium JIRA Archive
Titanium SDK/CLI (TIMOB)

[TIMOB-1977] Android: Backing out of window with other thread using proxies can cause FC

GitHub Issuen/a
TypeBug
PriorityMedium
StatusClosed
ResolutionFixed
Resolution Date2011-04-17T01:57:43.000+0000
Affected Version/sn/a
Fix Version/sRelease 1.5.0
ComponentsAndroid
Labelsandroid, defect
ReporterBill Dawson
AssigneeBill Dawson
Created2011-04-15T03:07:03.000+0000
Updated2011-04-17T01:57:43.000+0000

Description

If you back out of a window while a separate thread (such as a callback from an XHR, which is how we discovered this problem) is making use of proxy objects (view proxies and such) on that window, you can cause an FC. The FC can occur at multiple places in code, often in the form of a NullPointerException when trying to access something that doesn't exist anymore because the window's context and activity have been released. Here's a sample FC:

E/TiUncaughtHandler(  231): java.lang.NullPointerException
E/TiUncaughtHandler(  231):     at ti.modules.titanium.ui.TableViewProxy.rowProxyFor(TableViewProxy.java:400)
E/TiUncaughtHandler(  231):     at ti.modules.titanium.ui.TableViewProxy.handleInsertRowBefore(TableViewProxy.java:240)
E/TiUncaughtHandler(  231):     at ti.modules.titanium.ui.TableViewProxy.handleMessage(TableViewProxy.java:466)
E/TiUncaughtHandler(  231):     at android.os.Handler.dispatchMessage(Handler.java:95)
E/TiUncaughtHandler(  231):     at android.os.Looper.loop(Looper.java:123)
E/TiUncaughtHandler(  231):     at android.app.ActivityThread.main(ActivityThread.java:4203)
E/TiUncaughtHandler(  231):     at java.lang.reflect.Method.invokeNative(Native Method)
E/TiUncaughtHandler(  231):     at java.lang.reflect.Method.invoke(Method.java:521)

You can cause an FC using this app.js + win.js + table.js:

app.js:

Titanium.UI.setBackgroundColor('#000');
Titanium.UI.createWindow({  
    title:'Test',
    backgroundColor:'#fff',
    fullscreen: true,
    exitOnClose: true,
    url: 'win.js'
}).open();

win.js:

var win = Ti.UI.currentWindow;
var btn = Ti.UI.createButton({
    title: 'Open 2nd Window'
});
btn.addEventListener('click', function(){
    Ti.UI.createWindow( {
        fullscreen:true,
        url: 'table.js',
        backgroundColor: 'black'
    }).open();
});
win.add(btn);

table.js:

var win = Ti.UI.currentWindow;
var tv = Ti.UI.createTableView();
tv.setData( [ Ti.UI.createTableViewRow({ title: 'Loading...' }) ] );
win.add(tv);

// Now start a second thread that will update the table
setTimeout(function() {
    for (var i = 1; i <= 1000; i++) {
        tv.insertRowBefore(0, 
            Ti.UI.createTableViewRow( {title: 'New row ' + i} ));
    }
}, 50);

When you run it and you open the second window, click your hardware back button while the table is being assembled. After you get back to the first window, just wait a while and it'll crash.

Comments

  1. Bill Dawson 2011-04-15

    (from [763b1ded2db7f71fac628db4261770f292f9d283]) [#1977 state:fixed-in-qa] Avoid NPEs in several locations when an activity and context have been released but code on some thread (like an XHR callback) is still trying to work with them. http://github.com/appcelerator/titanium_mobile/commit/763b1ded2db7f71fac628db4261770f292f9d283"> http://github.com/appcelerator/titanium_mobile/commit/763b1ded2db7f...

  2. Thomas Huelbert 2011-04-15

    thanks for the test case, 1.4.2.4ce7ff G1 running 1.6, 2.2 simulator.

JSON Source