Titanium JIRA Archive
Appcelerator Community (AC)

[AC-396] Views loading images crash unpredictably, also causing database-opening exceptions

GitHub Issuen/a
TypeBug
Priorityn/a
StatusResolved
ResolutionCannot Reproduce
Resolution Date2015-11-22T11:52:14.000+0000
Affected Version/sn/a
Fix Version/sn/a
ComponentsTitanium SDK & CLI
Labelsandroid-4.4, crash, database, exception, image, view
ReporterRudolf Cardinal
AssigneeMostafizur Rahman
Created2015-03-12T10:01:11.000+0000
Updated2015-11-22T12:03:48.000+0000

Description

Summary

Views that load images into buttons crash unpredictably in this environment, with the following error: {noformat} E/BufferQueue( 292): [org.camcops.camcops/org.appcelerator.titanium.TiActivity] dequeueBuffer: can't dequeue multiple buffers without setting the buffer count {noformat} Subsequent attempts to open a database then crash with an exception (giving the impression of a database error): {noformat} E/SQLiteDatabase(25764): at org.appcelerator.titanium.proxy.TiViewProxy.handleMessage(TiViewProxy.java:347) W/System.err(25764): at org.appcelerator.titanium.proxy.TiViewProxy.handleMessage(TiViewProxy.java:347) E/TiExceptionHandler(25764): (main) [170,48824] ----- Titanium Javascript Runtime Error ----- E/TiExceptionHandler(25764): (main) [1,48825] - In undefined:32,32 E/TiExceptionHandler(25764): (main) [0,48825] - Message: Uncaught Error: Java Exception occurred E/TiExceptionHandler(25764): (main) [0,48825] - Source: var db = Titanium.Database.open(DBNAME), {noformat}

Effect

App becomes useless because it appears to hang unpredictably.

Test code to reproduce

/*jslint node: true, plusplus: true */
"use strict";
/*global Titanium */

var DBNAME = "junk.db",
    PKVAL = 1,
    ICONSIZE = 48,
    IM_PR = "/images/camcops/",  // image filename prefix
    ICON_RADIO_UNSELECTED = IM_PR + 'radio_unselected.png',
    ICON_RADIO_UNSELECTED_T = IM_PR + 'radio_unselected_T.png',
    ICON_RADIO_SELECTED = IM_PR + 'radio_selected.png',
    ICON_RADIO_SELECTED_T = IM_PR + 'radio_selected_T.png',
    view = Titanium.UI.createView({
        layout: 'vertical',
        backgroundColor: '#FFFFFF'
    }),
    button = Titanium.UI.createButton({
        width: ICONSIZE,
        height: ICONSIZE,
        touchEnabled: true,
        backgroundImage: ICON_RADIO_UNSELECTED,
        backgroundSelectedImage: ICON_RADIO_UNSELECTED_T,
    }),
    state = false,
    win = Titanium.UI.createWindow();

function rnd(min, max) {
    return Math.random() * (max - min) + min;
}

function standalone_execute_noreturn(query, args) {
    var db = Titanium.Database.open(DBNAME),
        cursor;
    if (args === undefined) {
        cursor = db.execute(query);
    } else {
        cursor = db.execute(query, args);
    }
    if (cursor !== null) {
        cursor.close();
    }
    db.close();
}

function access_db() {
    Titanium.API.info("access_db: start");
    standalone_execute_noreturn(
        "UPDATE t SET value = ? WHERE pk = ?",
        [rnd(0, 1000), PKVAL]
    );
    Titanium.API.info("access_db: end");
}

function makedb() {
    standalone_execute_noreturn(
        "CREATE TABLE IF NOT EXISTS t (pk INTEGER, value INTEGER)"
    );
}

function toggle_appearance() {
    Titanium.API.info("toggle_appearance: start");
    state = !state;
    if (state) {
        button.setBackgroundImage(ICON_RADIO_SELECTED);
        button.setBackgroundSelectedImage(ICON_RADIO_SELECTED_T);
    } else {
        button.setBackgroundImage(ICON_RADIO_UNSELECTED);
        button.setBackgroundSelectedImage(ICON_RADIO_UNSELECTED_T);
    }
    Titanium.API.info("toggle_appearance: end");
}

function click() {
    access_db();
    toggle_appearance();
}

makedb();
button.addEventListener("click", click);
view.add(button);
win.add(view);
win.open();

Procedure to generate crash

Tap the button frequently (usually crashes within first 100-200 taps or so).

Result if access_db() and toggle_appearance() are both called from click()

Crash (screen goes blank, though remains invisibly responsive) and exception from database access: Output from adb logcat | grep Ti: {noformat} ... I/TiAPI (25764): access_db: start I/TiAPI (25764): access_db: end I/TiAPI (25764): toggle_appearance: start I/TiAPI (25764): toggle_appearance: end I/TiAPI (25764): access_db: start I/TiAPI (25764): access_db: end I/TiAPI (25764): toggle_appearance: start I/TiAPI (25764): toggle_appearance: end I/TiAPI (25764): access_db: start I/TiAPI (25764): access_db: end I/TiAPI (25764): toggle_appearance: start I/TiAPI (25764): toggle_appearance: end I/TiAPI (25764): access_db: start I/TiAPI (25764): access_db: end I/TiAPI (25764): toggle_appearance: start I/TiAPI (25764): toggle_appearance: end I/TiAPI (25764): access_db: start I/TiAPI (25764): access_db: end I/TiAPI (25764): toggle_appearance: start I/TiAPI (25764): toggle_appearance: end I/TiAPI (25764): access_db: start I/TiAPI (25764): access_db: end I/TiAPI (25764): toggle_appearance: start I/TiAPI (25764): toggle_appearance: end I/TiAPI (25764): access_db: start I/TiAPI (25764): access_db: end I/TiAPI (25764): toggle_appearance: start I/TiAPI (25764): toggle_appearance: end E/BufferQueue( 292): [org.camcops.camcops/org.appcelerator.titanium.TiActivity] dequeueBuffer: can't dequeue multiple buffers without setting the buffer count I/TiAPI (25764): access_db: start I/TiAPI (25764): access_db: end I/TiAPI (25764): toggle_appearance: start I/TiAPI (25764): toggle_appearance: end E/BufferQueue( 292): [org.camcops.camcops/org.appcelerator.titanium.TiActivity] dequeueBuffer: can't dequeue multiple buffers without setting the buffer count E/BufferQueue( 292): [org.camcops.camcops/org.appcelerator.titanium.TiActivity] dequeueBuffer: can't dequeue multiple buffers without setting the buffer count I/TiAPI (25764): access_db: start E/SQLiteDatabase(25764): at org.appcelerator.titanium.proxy.TiViewProxy.handleMessage(TiViewProxy.java:347) W/System.err(25764): at org.appcelerator.titanium.proxy.TiViewProxy.handleMessage(TiViewProxy.java:347) E/TiExceptionHandler(25764): (main) [48442,48442] ----- Titanium Javascript Runtime Error ----- E/TiExceptionHandler(25764): (main) [0,48442] - In undefined:32,32 E/TiExceptionHandler(25764): (main) [1,48443] - Message: Uncaught Error: Java Exception occurred E/TiExceptionHandler(25764): (main) [0,48443] - Source: var db = Titanium.Database.open(DBNAME), I/TiAPI (25764): access_db: start E/SQLiteDatabase(25764): at org.appcelerator.titanium.proxy.TiViewProxy.handleMessage(TiViewProxy.java:347) W/System.err(25764): at org.appcelerator.titanium.proxy.TiViewProxy.handleMessage(TiViewProxy.java:347) E/TiExceptionHandler(25764): (main) [210,48653] ----- Titanium Javascript Runtime Error ----- E/TiExceptionHandler(25764): (main) [0,48653] - In undefined:32,32 E/TiExceptionHandler(25764): (main) [0,48653] - Message: Uncaught Error: Java Exception occurred E/TiExceptionHandler(25764): (main) [1,48654] - Source: var db = Titanium.Database.open(DBNAME), I/TiAPI (25764): access_db: start E/SQLiteDatabase(25764): at org.appcelerator.titanium.proxy.TiViewProxy.handleMessage(TiViewProxy.java:347) W/System.err(25764): at org.appcelerator.titanium.proxy.TiViewProxy.handleMessage(TiViewProxy.java:347) E/TiExceptionHandler(25764): (main) [170,48824] ----- Titanium Javascript Runtime Error ----- E/TiExceptionHandler(25764): (main) [1,48825] - In undefined:32,32 E/TiExceptionHandler(25764): (main) [0,48825] - Message: Uncaught Error: Java Exception occurred E/TiExceptionHandler(25764): (main) [0,48825] - Source: var db = Titanium.Database.open(DBNAME), I/TiAPI (25764): access_db: start E/SQLiteDatabase(25764): at org.appcelerator.titanium.proxy.TiViewProxy.handleMessage(TiViewProxy.java:347) W/System.err(25764): at org.appcelerator.titanium.proxy.TiViewProxy.handleMessage(TiViewProxy.java:347) E/TiExceptionHandler(25764): (main) [3777,52602] ----- Titanium Javascript Runtime Error ----- E/TiExceptionHandler(25764): (main) [0,52602] - In undefined:32,32 E/TiExceptionHandler(25764): (main) [1,52603] - Message: Uncaught Error: Java Exception occurred E/TiExceptionHandler(25764): (main) [0,52603] - Source: var db = Titanium.Database.open(DBNAME), {noformat} Full output from adb logcat: {noformat} ... I/TiAPI (27596): access_db: start I/TiAPI (27596): access_db: end I/TiAPI (27596): toggle_appearance: start I/TiAPI (27596): toggle_appearance: end I/TiAPI (27596): access_db: start I/TiAPI (27596): access_db: end I/TiAPI (27596): toggle_appearance: start I/TiAPI (27596): toggle_appearance: end I/TiAPI (27596): access_db: start I/TiAPI (27596): access_db: end I/TiAPI (27596): toggle_appearance: start I/TiAPI (27596): toggle_appearance: end I/TiAPI (27596): access_db: start I/TiAPI (27596): access_db: end I/TiAPI (27596): toggle_appearance: start I/TiAPI (27596): toggle_appearance: end I/TiAPI (27596): access_db: start I/TiAPI (27596): access_db: end I/TiAPI (27596): toggle_appearance: start I/TiAPI (27596): toggle_appearance: end E/QcrilMsgTunnelSocket( 2769): IOException - java.io.IOException: No such file or directory Reason: No such file or directory I/TiAPI (27596): access_db: start I/TiAPI (27596): access_db: end I/TiAPI (27596): toggle_appearance: start I/TiAPI (27596): toggle_appearance: end I/TiAPI (27596): access_db: start E/SQLiteLog(27596): (14) cannot open file at line 30185 of [00bb9c9ce4] E/SQLiteLog(27596): (14) os_unix.c:30185: (24) open(/data/data/org.camcops.camcops/databases/junk.db-journal) - E/SQLiteLog(27596): (14) cannot open file at line 30185 of [00bb9c9ce4] E/SQLiteLog(27596): (14) os_unix.c:30185: (24) open(/data/data/org.camcops.camcops/databases/junk.db-journal) - E/SQLiteLog(27596): (14) unable to open database file E/SQLiteDatabase(27596): Failed to open database '/data/data/org.camcops.camcops/databases/junk.db'. E/SQLiteDatabase(27596): android.database.sqlite.SQLiteCantOpenDatabaseException: unable to open database file (code 14): , while compiling: PRAGMA journal_mode E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method) E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:889) E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteConnection.executeForString(SQLiteConnection.java:634) E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteConnection.setJournalMode(SQLiteConnection.java:320) E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteConnection.setWalModeFromConfiguration(SQLiteConnection.java:294) E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:215) E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:193) E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463) E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185) E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177) E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:804) E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:789) E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:694) E/SQLiteDatabase(27596): at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:977) E/SQLiteDatabase(27596): at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:966) E/SQLiteDatabase(27596): at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:250) E/SQLiteDatabase(27596): at ti.modules.titanium.database.DatabaseModule.open(DatabaseModule.java:71) E/SQLiteDatabase(27596): at org.appcelerator.kroll.runtime.v8.V8Object.nativeFireEvent(Native Method) E/SQLiteDatabase(27596): at org.appcelerator.kroll.runtime.v8.V8Object.fireEvent(V8Object.java:62) E/SQLiteDatabase(27596): at org.appcelerator.kroll.KrollProxy.doFireEvent(KrollProxy.java:884) E/SQLiteDatabase(27596): at org.appcelerator.kroll.KrollProxy.handleMessage(KrollProxy.java:1107) E/SQLiteDatabase(27596): at org.appcelerator.titanium.proxy.TiViewProxy.handleMessage(TiViewProxy.java:347) E/SQLiteDatabase(27596): at android.os.Handler.dispatchMessage(Handler.java:98) E/SQLiteDatabase(27596): at android.os.Looper.loop(Looper.java:212) E/SQLiteDatabase(27596): at org.appcelerator.kroll.KrollRuntime$KrollRuntimeThread.run(KrollRuntime.java:112) W/System.err(27596): java.lang.NullPointerException W/System.err(27596): at ti.modules.titanium.database.DatabaseModule.open(DatabaseModule.java:78) W/System.err(27596): at org.appcelerator.kroll.runtime.v8.V8Object.nativeFireEvent(Native Method) W/System.err(27596): at org.appcelerator.kroll.runtime.v8.V8Object.fireEvent(V8Object.java:62) W/System.err(27596): at org.appcelerator.kroll.KrollProxy.doFireEvent(KrollProxy.java:884) W/System.err(27596): at org.appcelerator.kroll.KrollProxy.handleMessage(KrollProxy.java:1107) W/System.err(27596): at org.appcelerator.titanium.proxy.TiViewProxy.handleMessage(TiViewProxy.java:347) W/System.err(27596): at android.os.Handler.dispatchMessage(Handler.java:98) W/System.err(27596): at android.os.Looper.loop(Looper.java:212) W/System.err(27596): at org.appcelerator.kroll.KrollRuntime$KrollRuntimeThread.run(KrollRuntime.java:112) E/TiExceptionHandler(27596): (main) [36494,36494] ----- Titanium Javascript Runtime Error ----- E/TiExceptionHandler(27596): (main) [0,36494] - In undefined:32,32 E/TiExceptionHandler(27596): (main) [0,36494] - Message: Uncaught Error: Java Exception occurred E/TiExceptionHandler(27596): (main) [0,36494] - Source: var db = Titanium.Database.open(DBNAME), E/V8Exception(27596): Exception occurred at undefined:32: Uncaught Error: Java Exception occurred I/TiAPI (27596): access_db: start E/SQLiteLog(27596): (14) cannot open file at line 30185 of [00bb9c9ce4] E/SQLiteLog(27596): (14) os_unix.c:30185: (24) open(/data/data/org.camcops.camcops/databases/junk.db-journal) - E/SQLiteLog(27596): (14) cannot open file at line 30185 of [00bb9c9ce4] E/SQLiteLog(27596): (14) os_unix.c:30185: (24) open(/data/data/org.camcops.camcops/databases/junk.db-journal) - E/SQLiteLog(27596): (14) unable to open database file E/SQLiteDatabase(27596): Failed to open database '/data/data/org.camcops.camcops/databases/junk.db'. E/SQLiteDatabase(27596): android.database.sqlite.SQLiteCantOpenDatabaseException: unable to open database file (code 14): , while compiling: PRAGMA journal_mode E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method) E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:889) E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteConnection.executeForString(SQLiteConnection.java:634) E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteConnection.setJournalMode(SQLiteConnection.java:320) E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteConnection.setWalModeFromConfiguration(SQLiteConnection.java:294) E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:215) E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:193) E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463) E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185) E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177) E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:804) E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:789) E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:694) E/SQLiteDatabase(27596): at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:977) E/SQLiteDatabase(27596): at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:966) E/SQLiteDatabase(27596): at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:250) E/SQLiteDatabase(27596): at ti.modules.titanium.database.DatabaseModule.open(DatabaseModule.java:71) E/SQLiteDatabase(27596): at org.appcelerator.kroll.runtime.v8.V8Object.nativeFireEvent(Native Method) E/SQLiteDatabase(27596): at org.appcelerator.kroll.runtime.v8.V8Object.fireEvent(V8Object.java:62) E/SQLiteDatabase(27596): at org.appcelerator.kroll.KrollProxy.doFireEvent(KrollProxy.java:884) E/SQLiteDatabase(27596): at org.appcelerator.kroll.KrollProxy.handleMessage(KrollProxy.java:1107) E/SQLiteDatabase(27596): at org.appcelerator.titanium.proxy.TiViewProxy.handleMessage(TiViewProxy.java:347) E/SQLiteDatabase(27596): at android.os.Handler.dispatchMessage(Handler.java:98) E/SQLiteDatabase(27596): at android.os.Looper.loop(Looper.java:212) E/SQLiteDatabase(27596): at org.appcelerator.kroll.KrollRuntime$KrollRuntimeThread.run(KrollRuntime.java:112) W/System.err(27596): java.lang.NullPointerException W/System.err(27596): at ti.modules.titanium.database.DatabaseModule.open(DatabaseModule.java:78) W/System.err(27596): at org.appcelerator.kroll.runtime.v8.V8Object.nativeFireEvent(Native Method) W/System.err(27596): at org.appcelerator.kroll.runtime.v8.V8Object.fireEvent(V8Object.java:62) W/System.err(27596): at org.appcelerator.kroll.KrollProxy.doFireEvent(KrollProxy.java:884) W/System.err(27596): at org.appcelerator.kroll.KrollProxy.handleMessage(KrollProxy.java:1107) W/System.err(27596): at org.appcelerator.titanium.proxy.TiViewProxy.handleMessage(TiViewProxy.java:347) W/System.err(27596): at android.os.Handler.dispatchMessage(Handler.java:98) W/System.err(27596): at android.os.Looper.loop(Looper.java:212) W/System.err(27596): at org.appcelerator.kroll.KrollRuntime$KrollRuntimeThread.run(KrollRuntime.java:112) E/TiExceptionHandler(27596): (main) [126,36620] ----- Titanium Javascript Runtime Error ----- E/TiExceptionHandler(27596): (main) [0,36620] - In undefined:32,32 E/TiExceptionHandler(27596): (main) [1,36621] - Message: Uncaught Error: Java Exception occurred E/TiExceptionHandler(27596): (main) [0,36621] - Source: var db = Titanium.Database.open(DBNAME), E/V8Exception(27596): Exception occurred at undefined:32: Uncaught Error: Java Exception occurred I/TiAPI (27596): access_db: start E/SQLiteLog(27596): (14) cannot open file at line 30185 of [00bb9c9ce4] E/SQLiteLog(27596): (14) os_unix.c:30185: (24) open(/data/data/org.camcops.camcops/databases/junk.db-journal) - E/SQLiteLog(27596): (14) cannot open file at line 30185 of [00bb9c9ce4] E/SQLiteLog(27596): (14) os_unix.c:30185: (24) open(/data/data/org.camcops.camcops/databases/junk.db-journal) - E/SQLiteLog(27596): (14) unable to open database file E/SQLiteDatabase(27596): Failed to open database '/data/data/org.camcops.camcops/databases/junk.db'. E/SQLiteDatabase(27596): android.database.sqlite.SQLiteCantOpenDatabaseException: unable to open database file (code 14): , while compiling: PRAGMA journal_mode E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method) E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:889) E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteConnection.executeForString(SQLiteConnection.java:634) E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteConnection.setJournalMode(SQLiteConnection.java:320) E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteConnection.setWalModeFromConfiguration(SQLiteConnection.java:294) E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:215) E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:193) E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463) E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185) E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177) E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:804) E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:789) E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:694) E/SQLiteDatabase(27596): at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:977) E/SQLiteDatabase(27596): at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:966) E/SQLiteDatabase(27596): at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:250) E/SQLiteDatabase(27596): at ti.modules.titanium.database.DatabaseModule.open(DatabaseModule.java:71) E/SQLiteDatabase(27596): at org.appcelerator.kroll.runtime.v8.V8Object.nativeFireEvent(Native Method) E/SQLiteDatabase(27596): at org.appcelerator.kroll.runtime.v8.V8Object.fireEvent(V8Object.java:62) E/SQLiteDatabase(27596): at org.appcelerator.kroll.KrollProxy.doFireEvent(KrollProxy.java:884) E/SQLiteDatabase(27596): at org.appcelerator.kroll.KrollProxy.handleMessage(KrollProxy.java:1107) E/SQLiteDatabase(27596): at org.appcelerator.titanium.proxy.TiViewProxy.handleMessage(TiViewProxy.java:347) E/SQLiteDatabase(27596): at android.os.Handler.dispatchMessage(Handler.java:98) E/SQLiteDatabase(27596): at android.os.Looper.loop(Looper.java:212) E/SQLiteDatabase(27596): at org.appcelerator.kroll.KrollRuntime$KrollRuntimeThread.run(KrollRuntime.java:112) W/System.err(27596): java.lang.NullPointerException W/System.err(27596): at ti.modules.titanium.database.DatabaseModule.open(DatabaseModule.java:78) W/System.err(27596): at org.appcelerator.kroll.runtime.v8.V8Object.nativeFireEvent(Native Method) W/System.err(27596): at org.appcelerator.kroll.runtime.v8.V8Object.fireEvent(V8Object.java:62) W/System.err(27596): at org.appcelerator.kroll.KrollProxy.doFireEvent(KrollProxy.java:884) W/System.err(27596): at org.appcelerator.kroll.KrollProxy.handleMessage(KrollProxy.java:1107) W/System.err(27596): at org.appcelerator.titanium.proxy.TiViewProxy.handleMessage(TiViewProxy.java:347) W/System.err(27596): at android.os.Handler.dispatchMessage(Handler.java:98) W/System.err(27596): at android.os.Looper.loop(Looper.java:212) W/System.err(27596): at org.appcelerator.kroll.KrollRuntime$KrollRuntimeThread.run(KrollRuntime.java:112) E/TiExceptionHandler(27596): (main) [163,36784] ----- Titanium Javascript Runtime Error ----- E/TiExceptionHandler(27596): (main) [0,36784] - In undefined:32,32 E/TiExceptionHandler(27596): (main) [0,36784] - Message: Uncaught Error: Java Exception occurred E/TiExceptionHandler(27596): (main) [0,36784] - Source: var db = Titanium.Database.open(DBNAME), E/V8Exception(27596): Exception occurred at undefined:32: Uncaught Error: Java Exception occurred I/TiAPI (27596): access_db: start E/SQLiteLog(27596): (14) cannot open file at line 30185 of [00bb9c9ce4] E/SQLiteLog(27596): (14) os_unix.c:30185: (24) open(/data/data/org.camcops.camcops/databases/junk.db-journal) - E/SQLiteLog(27596): (14) cannot open file at line 30185 of [00bb9c9ce4] E/SQLiteLog(27596): (14) os_unix.c:30185: (24) open(/data/data/org.camcops.camcops/databases/junk.db-journal) - E/SQLiteLog(27596): (14) unable to open database file E/SQLiteDatabase(27596): Failed to open database '/data/data/org.camcops.camcops/databases/junk.db'. E/SQLiteDatabase(27596): android.database.sqlite.SQLiteCantOpenDatabaseException: unable to open database file (code 14): , while compiling: PRAGMA journal_mode E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method) E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:889) E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteConnection.executeForString(SQLiteConnection.java:634) E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteConnection.setJournalMode(SQLiteConnection.java:320) E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteConnection.setWalModeFromConfiguration(SQLiteConnection.java:294) E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:215) E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:193) E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463) E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185) E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177) E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:804) E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:789) E/SQLiteDatabase(27596): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:694) E/SQLiteDatabase(27596): at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:977) E/SQLiteDatabase(27596): at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:966) E/SQLiteDatabase(27596): at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:250) E/SQLiteDatabase(27596): at ti.modules.titanium.database.DatabaseModule.open(DatabaseModule.java:71) E/SQLiteDatabase(27596): at org.appcelerator.kroll.runtime.v8.V8Object.nativeFireEvent(Native Method) E/SQLiteDatabase(27596): at org.appcelerator.kroll.runtime.v8.V8Object.fireEvent(V8Object.java:62) E/SQLiteDatabase(27596): at org.appcelerator.kroll.KrollProxy.doFireEvent(KrollProxy.java:884) E/SQLiteDatabase(27596): at org.appcelerator.kroll.KrollProxy.handleMessage(KrollProxy.java:1107) E/SQLiteDatabase(27596): at org.appcelerator.titanium.proxy.TiViewProxy.handleMessage(TiViewProxy.java:347) E/SQLiteDatabase(27596): at android.os.Handler.dispatchMessage(Handler.java:98) E/SQLiteDatabase(27596): at android.os.Looper.loop(Looper.java:212) E/SQLiteDatabase(27596): at org.appcelerator.kroll.KrollRuntime$KrollRuntimeThread.run(KrollRuntime.java:112) W/System.err(27596): java.lang.NullPointerException W/System.err(27596): at ti.modules.titanium.database.DatabaseModule.open(DatabaseModule.java:78) W/System.err(27596): at org.appcelerator.kroll.runtime.v8.V8Object.nativeFireEvent(Native Method) W/System.err(27596): at org.appcelerator.kroll.runtime.v8.V8Object.fireEvent(V8Object.java:62) W/System.err(27596): at org.appcelerator.kroll.KrollProxy.doFireEvent(KrollProxy.java:884) W/System.err(27596): at org.appcelerator.kroll.KrollProxy.handleMessage(KrollProxy.java:1107) W/System.err(27596): at org.appcelerator.titanium.proxy.TiViewProxy.handleMessage(TiViewProxy.java:347) W/System.err(27596): at android.os.Handler.dispatchMessage(Handler.java:98) W/System.err(27596): at android.os.Looper.loop(Looper.java:212) W/System.err(27596): at org.appcelerator.kroll.KrollRuntime$KrollRuntimeThread.run(KrollRuntime.java:112) E/TiExceptionHandler(27596): (main) [132,36916] ----- Titanium Javascript Runtime Error ----- E/TiExceptionHandler(27596): (main) [1,36917] - In undefined:32,32 E/TiExceptionHandler(27596): (main) [0,36917] - Message: Uncaught Error: Java Exception occurred E/TiExceptionHandler(27596): (main) [0,36917] - Source: var db = Titanium.Database.open(DBNAME), E/V8Exception(27596): Exception occurred at undefined:32: Uncaught Error: Java Exception occurred {noformat}

Result if toggle_appearance() only is called from click()

Crash (screen goes blank though remains invisibly unresponsive); no Titanium exception this time (though there are underlying Android exceptions). Output from adb logcat | grep Ti: {noformat} ... I/TiAPI (26067): toggle_appearance: start I/TiAPI (26067): toggle_appearance: end I/TiAPI (26067): toggle_appearance: start I/TiAPI (26067): toggle_appearance: end I/TiAPI (26067): toggle_appearance: start I/TiAPI (26067): toggle_appearance: end I/TiAPI (26067): toggle_appearance: start I/TiAPI (26067): toggle_appearance: end I/TiAPI (26067): toggle_appearance: start I/TiAPI (26067): toggle_appearance: end I/TiAPI (26067): toggle_appearance: start I/TiAPI (26067): toggle_appearance: end I/TiAPI (26067): toggle_appearance: start I/TiAPI (26067): toggle_appearance: end I/TiAPI (26067): toggle_appearance: start I/TiAPI (26067): toggle_appearance: end I/TiAPI (26067): toggle_appearance: start I/TiAPI (26067): toggle_appearance: end I/TiAPI (26067): toggle_appearance: start I/TiAPI (26067): toggle_appearance: end I/TiAPI (26067): toggle_appearance: start I/TiAPI (26067): toggle_appearance: end I/TiAPI (26067): toggle_appearance: start I/TiAPI (26067): toggle_appearance: end I/TiAPI (26067): toggle_appearance: start I/TiAPI (26067): toggle_appearance: end I/TiAPI (26067): toggle_appearance: start I/TiAPI (26067): toggle_appearance: end E/BufferQueue( 292): [org.camcops.camcops/org.appcelerator.titanium.TiActivity] dequeueBuffer: can't dequeue multiple buffers without setting the buffer count I/TiAPI (26067): toggle_appearance: start I/TiAPI (26067): toggle_appearance: end E/BufferQueue( 292): [org.camcops.camcops/org.appcelerator.titanium.TiActivity] dequeueBuffer: can't dequeue multiple buffers without setting the buffer count E/BufferQueue( 292): [org.camcops.camcops/org.appcelerator.titanium.TiActivity] dequeueBuffer: can't dequeue multiple buffers without setting the buffer count I/TiAPI (26067): toggle_appearance: start I/TiAPI (26067): toggle_appearance: end {noformat} Full output from adb logcat (NB the message E/QcrilMsgTunnelSocket( 2769): IOException - java.io.IOException: No such file or directory Reason: No such file or directory appears spontaneously and is probably unrelated to this app): {noformat} ... I/TiAPI (28154): toggle_appearance: start I/TiAPI (28154): toggle_appearance: end I/TiAPI (28154): toggle_appearance: start I/TiAPI (28154): toggle_appearance: end I/TiAPI (28154): toggle_appearance: start I/TiAPI (28154): toggle_appearance: end I/TiAPI (28154): toggle_appearance: start I/TiAPI (28154): toggle_appearance: end I/TiAPI (28154): toggle_appearance: start I/TiAPI (28154): toggle_appearance: end I/TiAPI (28154): toggle_appearance: start I/TiAPI (28154): toggle_appearance: end I/TiAPI (28154): toggle_appearance: start I/TiAPI (28154): toggle_appearance: end I/TiAPI (28154): toggle_appearance: start I/TiAPI (28154): toggle_appearance: end D/skia (28154): ------- imageref_ashmem create failed <(null)> 36864 D/skia (28154): ------- imageref_ashmem create failed <(null)> 36864 D/skia (28154): ------- imageref_ashmem create failed <(null)> 36864 W/Adreno-EGLSUB(28154): : dequeue native buffer fail: Unknown error 2147483646, buffer=0x0, handle=0x0 E/BufferQueue( 292): [org.camcops.camcops/org.appcelerator.titanium.TiActivity] dequeueBuffer: can't dequeue multiple buffers without setting the buffer count W/Adreno-EGLSUB(28154): : dequeue native buffer fail: Invalid argument, buffer=0x0, handle=0x0 W/Adreno-EGL(28154): : EGL_BAD_SURFACE W/HardwareRenderer(28154): EGL error: EGL_BAD_SURFACE W/HardwareRenderer(28154): Mountain View, we've had a problem here. Switching back to software rendering. E/Surface (28154): dequeueBuffer: IGraphicBufferProducer::requestBuffer failed: -22 E/Surface (28154): dequeueBuffer failed (Invalid argument) E/ViewRootImpl(28154): Could not lock surface E/ViewRootImpl(28154): java.lang.IllegalArgumentException E/ViewRootImpl(28154): at android.view.Surface.nativeLockCanvas(Native Method) E/ViewRootImpl(28154): at android.view.Surface.lockCanvas(Surface.java:243) E/ViewRootImpl(28154): at android.view.ViewRootImpl.drawSoftware(ViewRootImpl.java:2435) E/ViewRootImpl(28154): at android.view.ViewRootImpl.draw(ViewRootImpl.java:2409) E/ViewRootImpl(28154): at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2253) E/ViewRootImpl(28154): at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1883) E/ViewRootImpl(28154): at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1000) E/ViewRootImpl(28154): at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5607) E/ViewRootImpl(28154): at android.view.Choreographer$CallbackRecord.run(Choreographer.java:761) E/ViewRootImpl(28154): at android.view.Choreographer.doCallbacks(Choreographer.java:574) E/ViewRootImpl(28154): at android.view.Choreographer.doFrame(Choreographer.java:544) E/ViewRootImpl(28154): at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:747) E/ViewRootImpl(28154): at android.os.Handler.handleCallback(Handler.java:733) E/ViewRootImpl(28154): at android.os.Handler.dispatchMessage(Handler.java:95) E/ViewRootImpl(28154): at android.os.Looper.loop(Looper.java:212) E/ViewRootImpl(28154): at android.app.ActivityThread.main(ActivityThread.java:5137) E/ViewRootImpl(28154): at java.lang.reflect.Method.invokeNative(Native Method) E/ViewRootImpl(28154): at java.lang.reflect.Method.invoke(Method.java:515) E/ViewRootImpl(28154): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:902) E/ViewRootImpl(28154): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:718) E/ViewRootImpl(28154): at dalvik.system.NativeStart.main(Native Method) I/TiAPI (28154): toggle_appearance: start I/TiAPI (28154): toggle_appearance: end D/skia (28154): ------- imageref_ashmem create failed <(null)> 36864 D/skia (28154): ------- imageref_ashmem create failed <(null)> 36864 D/skia (28154): ------- imageref_ashmem create failed <(null)> 36864 D/skia (28154): ------- imageref_ashmem create failed <(null)> 36864 D/skia (28154): ------- imageref_ashmem create failed <(null)> 36864 D/skia (28154): ------- imageref_ashmem create failed <(null)> 36864 E/BufferQueue( 292): [org.camcops.camcops/org.appcelerator.titanium.TiActivity] dequeueBuffer: can't dequeue multiple buffers without setting the buffer count E/Surface (28154): dequeueBuffer failed (Invalid argument) E/ViewRootImpl(28154): Could not lock surface E/ViewRootImpl(28154): java.lang.IllegalArgumentException E/ViewRootImpl(28154): at android.view.Surface.nativeLockCanvas(Native Method) E/ViewRootImpl(28154): at android.view.Surface.lockCanvas(Surface.java:243) E/ViewRootImpl(28154): at android.view.ViewRootImpl.drawSoftware(ViewRootImpl.java:2435) E/ViewRootImpl(28154): at android.view.ViewRootImpl.draw(ViewRootImpl.java:2409) E/ViewRootImpl(28154): at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2253) E/ViewRootImpl(28154): at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1883) E/ViewRootImpl(28154): at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1000) E/ViewRootImpl(28154): at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5607) E/ViewRootImpl(28154): at android.view.Choreographer$CallbackRecord.run(Choreographer.java:761) E/ViewRootImpl(28154): at android.view.Choreographer.doCallbacks(Choreographer.java:574) E/ViewRootImpl(28154): at android.view.Choreographer.doFrame(Choreographer.java:544) E/ViewRootImpl(28154): at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:747) E/ViewRootImpl(28154): at android.os.Handler.handleCallback(Handler.java:733) E/ViewRootImpl(28154): at android.os.Handler.dispatchMessage(Handler.java:95) E/ViewRootImpl(28154): at android.os.Looper.loop(Looper.java:212) E/ViewRootImpl(28154): at android.app.ActivityThread.main(ActivityThread.java:5137) E/ViewRootImpl(28154): at java.lang.reflect.Method.invokeNative(Native Method) E/ViewRootImpl(28154): at java.lang.reflect.Method.invoke(Method.java:515) E/ViewRootImpl(28154): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:902) E/ViewRootImpl(28154): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:718) E/ViewRootImpl(28154): at dalvik.system.NativeStart.main(Native Method) E/BufferQueue( 292): [org.camcops.camcops/org.appcelerator.titanium.TiActivity] dequeueBuffer: can't dequeue multiple buffers without setting the buffer count E/Surface (28154): dequeueBuffer failed (Invalid argument) E/ViewRootImpl(28154): Could not lock surface E/ViewRootImpl(28154): java.lang.IllegalArgumentException E/ViewRootImpl(28154): at android.view.Surface.nativeLockCanvas(Native Method) E/ViewRootImpl(28154): at android.view.Surface.lockCanvas(Surface.java:243) E/ViewRootImpl(28154): at android.view.ViewRootImpl.drawSoftware(ViewRootImpl.java:2435) E/ViewRootImpl(28154): at android.view.ViewRootImpl.draw(ViewRootImpl.java:2409) E/ViewRootImpl(28154): at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2253) E/ViewRootImpl(28154): at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1883) E/ViewRootImpl(28154): at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1000) E/ViewRootImpl(28154): at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5607) E/ViewRootImpl(28154): at android.view.Choreographer$CallbackRecord.run(Choreographer.java:761) E/ViewRootImpl(28154): at android.view.Choreographer.doCallbacks(Choreographer.java:574) E/ViewRootImpl(28154): at android.view.Choreographer.doFrame(Choreographer.java:544) E/ViewRootImpl(28154): at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:747) E/ViewRootImpl(28154): at android.os.Handler.handleCallback(Handler.java:733) E/ViewRootImpl(28154): at android.os.Handler.dispatchMessage(Handler.java:95) E/ViewRootImpl(28154): at android.os.Looper.loop(Looper.java:212) E/ViewRootImpl(28154): at android.app.ActivityThread.main(ActivityThread.java:5137) E/ViewRootImpl(28154): at java.lang.reflect.Method.invokeNative(Native Method) E/ViewRootImpl(28154): at java.lang.reflect.Method.invoke(Method.java:515) E/ViewRootImpl(28154): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:902) E/ViewRootImpl(28154): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:718) E/ViewRootImpl(28154): at dalvik.system.NativeStart.main(Native Method) I/TiAPI (28154): toggle_appearance: start I/TiAPI (28154): toggle_appearance: end D/skia (28154): ------- imageref_ashmem create failed <(null)> 36864 D/skia (28154): ------- imageref_ashmem create failed <(null)> 36864 D/skia (28154): ------- imageref_ashmem create failed <(null)> 36864 D/skia (28154): ------- imageref_ashmem create failed <(null)> 36864 D/skia (28154): ------- imageref_ashmem create failed <(null)> 36864 D/skia (28154): ------- imageref_ashmem create failed <(null)> 36864 D/skia (28154): ------- imageref_ashmem create failed <(null)> 36864 D/skia (28154): ------- imageref_ashmem create failed <(null)> 36864 {noformat}

Result if access_db() only is called from click()

Haven't managed to get a crash out of this (nor by calling access_db() 10,000 times consecutively).

Plausible fixes that didn't help

Setting <application android:hardwareAccelerated="false"> in tiapp.xml made no difference.

Theories

Possible sequence (I have no idea if this is the case):

File handle leak

-> Crash in Android display code

-> Crash in other file access (e.g. database opening) operations?

Possible related Android bugs

[https://code.google.com/p/android/issues/detail?id=63738] [https://code.google.com/p/android/issues/detail?id=71742]

Attachments

FileDateSize
radio_selected_T.png2015-03-12T10:01:11.000+00006094
radio_selected.png2015-03-12T10:01:11.000+00004346
radio_unselected_T.png2015-03-12T10:01:11.000+00005479
radio_unselected.png2015-03-12T10:01:11.000+00003264

Comments

  1. Rudolf Cardinal 2015-04-21

    This is not resolved by replacing all setBackgroundImage() calls with an equivalent system of show()/hide() calls on views/buttons. App still crashes. Could this be triaged, please? It has broken the app completely.
  2. Rudolf Cardinal 2015-04-22

    Further diagnostics

    * Crash is the imageref_ashmem create failed message, from [https://code.google.com/p/skia/source/browse/trunk/src/images/SkImageRef_ashmem.cpp?spec=svn11558&r=11558] . * *Consequence* of crash appears to be that the rest of the application/UI interface gets taken down (sometimes partially, ?an individual thread crashes) -- so that the database access, UI, etc., subsequently fail. * *Lowest-level reason* for crash appears to be running out of memory. In support of that supposition, this problem occurs more frequently when lots of buttons are used. Replacing buttons (having setBackgroundImage()/setBackgroundSelectedImage() calls) with images (using show()/hide()), passing filenames to the ImageView creation, made the crash occur earlier. Specifically, the crash then occurred at initial image loading, rather than after dozens of touches, presumably because e.g. 26 widgets * 4 images per widget * 36864 bytes per image on this Android tablet's display = 3.8 Mb = too much. * *Guess* about reason for crash in code above is therefore a memory leak.

    Workaround

    Use images rather than buttons, using setImage() to change their appearance when touched, AND

    Create those images (img = createImageView({image: XXX, ...}) and change their appearance (img.setImage(XXX)) using cached Blobs, rather than filenames, to save memory. Caching code example below.

    This also makes the display load much faster. However, it does not allow the pseudo-buttons to appear different whilst being touched, as ImageView does not have the setBackgroundSelectedImage method, so it's visually less good. An ideal solution might be to use a button and pass a Blob rather than a filename to its creation and image-setting methods; however, it appears that for some reason, Titanium.UI.Button doesn't support Blob parameters to its background image functions (just filenames/URLs). Another ideal solution would be an SDK bugfix to the leak, if a leak is what's happening!

    Specimen image-caching code

    Note that the platform module referred to here simply defines constants relating to which platform Titanium is running on; replace those with standalone code for real use.
       /*jslint node: true */
       "use strict";
       /*global Titanium */
       
       var cache = {},
           platform = require('lib/platform');
       
       function reportCacheSize() {
           var key,
               size = 0;
           for (key in cache) {
               if (cache.hasOwnProperty(key) && cache[key].length !== undefined) {
                   size += cache[key].length;
               }
           }
           Titanium.API.info("Image cache size: " + size);
       }
       
       function getImage(filename) {
           var file;
           if (!cache.hasOwnProperty(filename) || cache[filename] === null) {
               Titanium.API.info("Caching image: " + filename);
               if (platform.mobileweb) {
                   // ImageView creating using Blob/File objects not supported under
                   // MobileWeb.
                   cache[filename] = filename;
               } else {
                   file = Titanium.Filesystem.getFile(
                       Titanium.Filesystem.resourcesDirectory,
                       filename
                   );
                   if (!file.exists()) {
                       Titanium.API.warn("File doesn't exist: " + filename);
                       return null;
                   }
                   cache[filename] = file.read();
               }
               reportCacheSize();
           }
           return cache[filename];
       }
       exports.getImage = getImage;
       
       function clearCache() {
           var key;
           for (key in cache) {
               if (cache.hasOwnProperty(key)) {  // for JSLint
                   cache[key] = null;  // for garbage collection
               }
           }
           cache = {};
           reportCacheSize();
       }
       exports.clearCache = clearCache;
       
    ... and then in main code, one can replace img.setImage(FILENAME) with img.setImage(imagecache.getImage(FILENAME)).
  3. Jebun Naher 2015-11-15

    Hello, We tested this issue but couldn't reproduce it as a bug in our working environment. App runs successfully with no crash log. [Screenshot](http://postimg.org/image/oqflpjpkl/) *Console Log:*
       [INFO] :   access_db: start
       [INFO] :   access_db: end
       [INFO] :   toggle_appearance: start
       [INFO] :   toggle_appearance: end
       
    *Testing Environment:* Appcelerator Studio, build: 4.3.3.201510212245 Appcelerator Command-Line Interface, version 5.0.4 Mac Osx: 10.9.5 Ti sdk : 5.0.2 Node.js Version : 0.12.7 Jdk: 1.7.0_65 Emulator : Samsung Galaxy S4(4.4.4); Device: Samsung Galaxy S3 *Test Code*
       /*jslint node: true, plusplus: true */
       "use strict";
       /*global Titanium */
       
       var DBNAME = "junk.db",
           PKVAL = 1,
           ICONSIZE = 48,
           IM_PR = "/images/camcops/", // image filename prefix
           ICON_RADIO_UNSELECTED = IM_PR + 'radio_unselected.png',
           ICON_RADIO_UNSELECTED_T = IM_PR + 'radio_unselected_T.png',
           ICON_RADIO_SELECTED = IM_PR + 'radio_selected.png',
           ICON_RADIO_SELECTED_T = IM_PR + 'radio_selected_T.png',
           view = Titanium.UI.createView({
       	layout : 'vertical',
       	backgroundColor : '#FFFFFF'
       }),
           button = Titanium.UI.createButton({
       	width : ICONSIZE,
       	height : ICONSIZE,
       	touchEnabled : true,
       	backgroundImage : ICON_RADIO_UNSELECTED,
       	backgroundSelectedImage : ICON_RADIO_UNSELECTED_T,
       }),
           state = false,
           win = Titanium.UI.createWindow();
       
       function rnd(min, max) {
       	return Math.random() * (max - min) + min;
       }
       
       function standalone_execute_noreturn(query, args) {
       	var db = Titanium.Database.open(DBNAME),
       	    cursor;
       	if (args === undefined) {
       		cursor = db.execute(query);
       	} else {
       		cursor = db.execute(query, args);
       	}
       	if (cursor !== null) {
       		cursor.close();
       	}
       	db.close();
       }
       
       function access_db() {
       	Titanium.API.info("access_db: start");
       	standalone_execute_noreturn("UPDATE t SET value = ? WHERE pk = ?", [rnd(0, 1000), PKVAL]);
       	Titanium.API.info("access_db: end");
       }
       
       function makedb() {
       	standalone_execute_noreturn("CREATE TABLE IF NOT EXISTS t (pk INTEGER, value INTEGER)");
       }
       
       function toggle_appearance() {
       	Titanium.API.info("toggle_appearance: start");
       	state = !state;
       	if (state) {
       		button.setBackgroundImage(ICON_RADIO_SELECTED);
       		button.setBackgroundSelectedImage(ICON_RADIO_SELECTED_T);
       	} else {
       		button.setBackgroundImage(ICON_RADIO_UNSELECTED);
       		button.setBackgroundSelectedImage(ICON_RADIO_UNSELECTED_T);
       	}
       	Titanium.API.info("toggle_appearance: end");
       }
       function click() {
       	access_db();
       	toggle_appearance();
       }
       makedb();
       button.addEventListener("click", click);
       view.add(button);
       win.add(view);
       win.open(); 
       
    *Steps to test:* 1. Paste the reporter code in app.js file. 2. Create a "/images/camcops" folder inside the resource folder. 3. And paste the attached image to that folder. 4. Run with the testing environment. 5. Then Tap the button frequently Thanks.

JSON Source