System.Data.SQLite
Check-in [ed16f61cf7]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Fix a couple more potential GC race conditions.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: ed16f61cf74671ec01c49ac6209c035318f0eeed
User & Date: mistachkin 2012-05-03 15:11:34
Context
2012-05-03
15:58
Fix yet another set of GC race conditions. check-in: 8c76674915 user: mistachkin tags: trunk
15:11
Fix a couple more potential GC race conditions. check-in: ed16f61cf7 user: mistachkin tags: trunk
13:44
Do not attempt to reset a connection if it has been closed. Also, prevent any potential GC race while resetting a connection. Keep track of the total number of connections successfully opened and closed from any of the pools. Enhance test for ticket [996d13cd87] to make sure that at least one connection was opened and closed from a connection pool. check-in: 7b3fe92dcb user: mistachkin tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to System.Data.SQLite/SQLite3.cs.

188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
      }
    }

    internal override bool AutoCommit
    {
      get
      {
        return IsAutocommit(_sql);
      }
    }

    internal override long LastInsertRowId
    {
      get
      {







|







188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
      }
    }

    internal override bool AutoCommit
    {
      get
      {
        return IsAutocommit(_sql, _sql);
      }
    }

    internal override long LastInsertRowId
    {
      get
      {

Changes to System.Data.SQLite/SQLiteBase.cs.

343
344
345
346
347
348
349
350



351
352
353
354
355
356
357
358
359
360




361
362
363
364
365
366
367
...
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428



429
430



431
432
433
434
435
436
437
438
    // They exist here because they are called during the finalization of
    // a SQLiteStatementHandle, SQLiteConnectionHandle, and SQLiteFunctionCookieHandle.
    // Therefore these functions have to be static, and have to be low-level.

    internal static string GetLastError(SQLiteConnectionHandle hdl, IntPtr db)
    {
        if ((hdl == null) || (db == IntPtr.Zero))
            return "invalid connection or database handle";




        lock (hdl)
        {
#if !SQLITE_STANDARD
            int len;
            return UTF8ToString(UnsafeNativeMethods.sqlite3_errmsg_interop(db, out len), len);
#else
            return UTF8ToString(UnsafeNativeMethods.sqlite3_errmsg(db), -1);
#endif
        }




    }

    internal static void FinishBackup(IntPtr backup)
    {
        if (backup == IntPtr.Zero) return;
        int n = UnsafeNativeMethods.sqlite3_backup_finish(backup);
        if (n > 0) throw new SQLiteException(n, null);
................................................................................
                    n = UnsafeNativeMethods.sqlite3_reset_interop(stmt);
#else
                    n = UnsafeNativeMethods.sqlite3_reset(stmt);
#endif
                }
            } while (stmt != IntPtr.Zero);

            if (IsAutocommit(db) == false) // a transaction is pending on the connection
            {
                n = UnsafeNativeMethods.sqlite3_exec(db, ToUTF8("ROLLBACK"), IntPtr.Zero, IntPtr.Zero, out stmt);
                if (n > 0) throw new SQLiteException(n, GetLastError(hdl, db));
            }
        }
        GC.KeepAlive(hdl);
    }

    internal static bool IsAutocommit(IntPtr db)
    {
      if (db == IntPtr.Zero) return false;



      return (UnsafeNativeMethods.sqlite3_get_autocommit(db) == 1);
    }




  }

  internal interface ISQLiteSchemaExtensions
  {
    void BuildTempSchema(SQLiteConnection cnn);
  }








|
>
>
>










>
>
>
>







 







|








|


>
>
>
|
|
>
>
>
|







343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
...
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
    // They exist here because they are called during the finalization of
    // a SQLiteStatementHandle, SQLiteConnectionHandle, and SQLiteFunctionCookieHandle.
    // Therefore these functions have to be static, and have to be low-level.

    internal static string GetLastError(SQLiteConnectionHandle hdl, IntPtr db)
    {
        if ((hdl == null) || (db == IntPtr.Zero))
            return "null connection or database handle";

        if (hdl.IsClosed || hdl.IsInvalid)
            return "closed or invalid connection handle";

        lock (hdl)
        {
#if !SQLITE_STANDARD
            int len;
            return UTF8ToString(UnsafeNativeMethods.sqlite3_errmsg_interop(db, out len), len);
#else
            return UTF8ToString(UnsafeNativeMethods.sqlite3_errmsg(db), -1);
#endif
        }

#pragma warning disable 162
        GC.KeepAlive(hdl); /* NOTE: Unreachable code. */
#pragma warning restore 162
    }

    internal static void FinishBackup(IntPtr backup)
    {
        if (backup == IntPtr.Zero) return;
        int n = UnsafeNativeMethods.sqlite3_backup_finish(backup);
        if (n > 0) throw new SQLiteException(n, null);
................................................................................
                    n = UnsafeNativeMethods.sqlite3_reset_interop(stmt);
#else
                    n = UnsafeNativeMethods.sqlite3_reset(stmt);
#endif
                }
            } while (stmt != IntPtr.Zero);

            if (IsAutocommit(hdl, db) == false) // a transaction is pending on the connection
            {
                n = UnsafeNativeMethods.sqlite3_exec(db, ToUTF8("ROLLBACK"), IntPtr.Zero, IntPtr.Zero, out stmt);
                if (n > 0) throw new SQLiteException(n, GetLastError(hdl, db));
            }
        }
        GC.KeepAlive(hdl);
    }

    internal static bool IsAutocommit(SQLiteConnectionHandle hdl, IntPtr db)
    {
      if (db == IntPtr.Zero) return false;
      if (hdl.IsClosed || hdl.IsInvalid) return false;
      lock (hdl)
      {
          return (UnsafeNativeMethods.sqlite3_get_autocommit(db) == 1);
      }
#pragma warning disable 162
      GC.KeepAlive(hdl); /* NOTE: Unreachable code. */
#pragma warning restore 162
    }
  }

  internal interface ISQLiteSchemaExtensions
  {
    void BuildTempSchema(SQLiteConnection cnn);
  }