Matt
Matt

Reputation: 367

Android & SQLite - Occasional error 'unable to close due to unfinalised statements'

I seem to get the above error every so often in (an insert heavy) part of my code. I know normally this means there is an open Cursor within the connection but I have been through checking all my cursors are in try finally blocks and closed. Also in logcat the error reads 'sqlite3_close(...) failed: 5 which I think means the database is busy?

The error can be 'ignored' if I add the following code to my finally block where the database connection is closed.

  finally
  {
    writer.endTransaction();
    boolean successAtClose = false;
    while(successAtClose == false)
    {
      try
      {
        writer.close();
        successAtClose = true;
      }
      catch(Exception e)
      {
        e.printStackTrace();
      }
    }
    dbConn.releaseLock();
  }

When stepping through the code above the 'e.printStackTrace()' is hit once but on the second attempt the 'writer.close()' does not throw an error.

Just to reiterate, this problem doesn't even happen every time the code block runs, the same data can be inserted say 5/6 times and only throw the error on one of these times. In addition the error does not reoccur straight away after happening once but continues to pop-up at random intervals.

Does anyone know why this might occur? Or a better way to recover from this than the finally code above? (Since it will take me a long time to add this to all my database code.)

ADDED:

Database is opened with a custom SQLiteOpenHelper which is extended to use a reentrant lock to ensure only one thread accesses the database at any one time. So the start of the code is like:

  MyDatabaseHelper dbConn = MyDatabaseHelper.getDatabaseAccess(c);//await availability/lock the database here
  SQLiteDatabase writer = dbConn.getWritableDatabase();     
    try
    {       
        writer.beginTransaction();

        //do inserts

        writer.setTransactionSuccessful();

Get database access as follows:

  public static MyDatabaseHelper getDatabaseAccess(Context c)
  {      
    l.lock();       
    return new MyDatabaseHelper(c);
  }

As a further test I have further added a Thread.sleep() call to the finally code (in my case of 12 seconds), before the close() but after the endTransaction(), that seems to have stopped the error and confirm it is not a case of an open cursor, but I would rather not rely on a timer. If there is a better way, perhaps to pre-check whether the database is busy, please share.

Upvotes: 0

Views: 2544

Answers (3)

Douglas Jones
Douglas Jones

Reputation: 2542

If you are using SQLiteStatement or SQLiteQuery objects to work with your database you need to make sure they get closed out as well. If it's SQLiteClosable you need to close it.

Upvotes: 1

laalto
laalto

Reputation: 152857

The workaround is incorrect. close() decrements a reference counter and only when the counter hits exactly zero is the actual resource disposal i.e. sqlite3_close() attempted. On the second call the counter will be negative and the call will be a no-op.

You are correct that error code 5 is SQLITE_BUSY.

Now to address the actual problem, please provide some additional details, such as how you open and configure the database and how you begin your transactions.

Upvotes: 0

Akhilesh Sk
Akhilesh Sk

Reputation: 451

This mainly happens when you haven't closed the cursor, meant certain references to the database were invalid.

refer ths link Android SQLite Exception: unable to close due to unfinalised statements

Upvotes: 0

Related Questions