Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Synchronize access to the '_enlistment' field of SQLiteConnection objects. Even thought the SQLiteConnection class is not designed to be thread-safe, this field must be protected from multi-threaded access due to how (asynchronous) transaction scope completion is implemented by the .NET Framework. Candidate fix for ticket [5cee5409f8]. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | tkt-5cee5409f8 |
Files: | files | file ages | folders |
SHA1: |
8f44046b6f67264564c507807abae51b |
User & Date: | mistachkin 2018-01-24 18:11:17.617 |
Original Comment: | Synchronize access to the '_enlistment' field of SQLiteConnection objects. Even thought the SQLiteConnection class is not designed to be thread-safe, this field must be protected from multi-threaded access due to (asynchronous) transaction scope completion is implemented by the .NET Framework. Candidate fix for ticket [5cee5409f8]. |
Context
2018-01-25
| ||
18:53 | In the enlistment cleanup, validate the 'cnn' parameter prior to attempting to use it. check-in: 6ec25f2c57 user: mistachkin tags: tkt-5cee5409f8 | |
2018-01-24
| ||
18:11 | Synchronize access to the '_enlistment' field of SQLiteConnection objects. Even thought the SQLiteConnection class is not designed to be thread-safe, this field must be protected from multi-threaded access due to how (asynchronous) transaction scope completion is implemented by the .NET Framework. Candidate fix for ticket [5cee5409f8]. check-in: 8f44046b6f user: mistachkin tags: tkt-5cee5409f8 | |
2018-01-23
| ||
00:44 | Update the Eagle shell configuration file. check-in: f722d13e2d user: mistachkin tags: trunk | |
Changes
Changes to System.Data.SQLite/SQLiteConnection.cs.
︙ | ︙ | |||
1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 | /// <summary> /// The default isolation level for new transactions /// </summary> private IsolationLevel _defaultIsolation; #if !PLATFORM_COMPACTFRAMEWORK /// <summary> /// Whether or not the connection is enlisted in a distrubuted transaction /// </summary> internal SQLiteEnlistment _enlistment; #endif /// <summary> | > > > > > > | 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 | /// <summary> /// The default isolation level for new transactions /// </summary> private IsolationLevel _defaultIsolation; #if !PLATFORM_COMPACTFRAMEWORK /// <summary> /// This object is used with lock statements to synchronize access to the /// <see cref="_enlistment" /> field, below. /// </summary> internal readonly object _enlistmentSyncRoot = new object(); /// <summary> /// Whether or not the connection is enlisted in a distrubuted transaction /// </summary> internal SQLiteEnlistment _enlistment; #endif /// <summary> |
︙ | ︙ | |||
2895 2896 2897 2898 2899 2900 2901 | OnChanged(this, new ConnectionEventArgs( SQLiteConnectionEventType.Closing, null, null, null, null, null, null, null)); if (_sql != null) { #if !PLATFORM_COMPACTFRAMEWORK | > > | | | | | | | | | | | | | | | | > | 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 | OnChanged(this, new ConnectionEventArgs( SQLiteConnectionEventType.Closing, null, null, null, null, null, null, null)); if (_sql != null) { #if !PLATFORM_COMPACTFRAMEWORK lock (_enlistmentSyncRoot) /* TRANSACTIONAL */ { if (_enlistment != null) { // If the connection is enlisted in a transaction scope and the scope is still active, // we cannot truly shut down this connection until the scope has completed. Therefore make a // hidden connection temporarily to hold open the connection until the scope has completed. SQLiteConnection cnn = new SQLiteConnection(); cnn._sql = _sql; cnn._transactionLevel = _transactionLevel; cnn._transactionSequence = _transactionSequence; cnn._enlistment = _enlistment; cnn._connectionState = _connectionState; cnn._version = _version; _enlistment._transaction._cnn = cnn; _enlistment._disposeConnection = true; _sql = null; _enlistment = null; } } #endif if (_sql != null) { _sql.Close(_disposing); _sql = null; } |
︙ | ︙ | |||
3363 3364 3365 3366 3367 3368 3369 | #if !PLATFORM_COMPACTFRAMEWORK /// <summary> /// Manual distributed transaction enlistment support /// </summary> /// <param name="transaction">The distributed transaction to enlist in</param> public override void EnlistTransaction(System.Transactions.Transaction transaction) { | | > > | | | | | | | | | | | | | | | | > | 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 | #if !PLATFORM_COMPACTFRAMEWORK /// <summary> /// Manual distributed transaction enlistment support /// </summary> /// <param name="transaction">The distributed transaction to enlist in</param> public override void EnlistTransaction(System.Transactions.Transaction transaction) { CheckDisposed(); lock (_enlistmentSyncRoot) /* TRANSACTIONAL */ { if (_enlistment != null && transaction == _enlistment._scope) return; else if (_enlistment != null) throw new ArgumentException("Already enlisted in a transaction"); if (_transactionLevel > 0 && transaction != null) throw new ArgumentException("Unable to enlist in transaction, a local transaction already exists"); else if (transaction == null) throw new ArgumentNullException("Unable to enlist in transaction, it is null"); bool strictEnlistment = ((_flags & SQLiteConnectionFlags.StrictEnlistment) == SQLiteConnectionFlags.StrictEnlistment); _enlistment = new SQLiteEnlistment(this, transaction, GetFallbackDefaultIsolationLevel(), strictEnlistment, strictEnlistment); OnChanged(this, new ConnectionEventArgs( SQLiteConnectionEventType.EnlistTransaction, null, null, null, null, null, null, new object[] { _enlistment })); } } #endif /// <summary> /// Looks for a key in the array of key/values of the parameter string. If not found, return the specified default value /// </summary> /// <param name="items">The list to look in</param> |
︙ | ︙ |
Changes to System.Data.SQLite/SQLiteEnlistment.cs.
︙ | ︙ | |||
183 184 185 186 187 188 189 | #region IEnlistmentNotification Members public void Commit(Enlistment enlistment) { CheckDisposed(); SQLiteConnection cnn = _transaction.Connection; | > > > | > | 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 | #region IEnlistmentNotification Members public void Commit(Enlistment enlistment) { CheckDisposed(); SQLiteConnection cnn = _transaction.Connection; lock (cnn._enlistmentSyncRoot) { cnn._enlistment = null; } try { _transaction.IsValid(true); _transaction.Connection._transactionLevel = 1; _transaction.Commit(); |
︙ | ︙ | |||
226 227 228 229 230 231 232 | /////////////////////////////////////////////////////////////////////////// public void Rollback(Enlistment enlistment) { CheckDisposed(); SQLiteConnection cnn = _transaction.Connection; | > > > | > | 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 | /////////////////////////////////////////////////////////////////////////// public void Rollback(Enlistment enlistment) { CheckDisposed(); SQLiteConnection cnn = _transaction.Connection; lock (cnn._enlistmentSyncRoot) { cnn._enlistment = null; } try { _transaction.Rollback(); enlistment.Done(); } finally |
︙ | ︙ |