From 76ced43ebff5a6ca7772cc28578663796a987eb4 Mon Sep 17 00:00:00 2001 From: Kaur-Parminder Date: Mon, 23 Aug 2021 16:33:22 -0700 Subject: [PATCH 1/2] Fix unknown transaction state issues when promoting delegated transaction --- .../Data/SqlClient/SqlDelegatedTransaction.cs | 17 +++++++++++++++-- .../Data/SqlClient/SqlDelegatedTransaction.cs | 17 +++++++++++++++-- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlDelegatedTransaction.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlDelegatedTransaction.cs index e861c7ec31..d2ae5d031c 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlDelegatedTransaction.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlDelegatedTransaction.cs @@ -208,9 +208,22 @@ public byte[] Promote() } //Throw exception only if Transaction is still active and not yet aborted. - if (promoteException != null && Transaction.TransactionInformation.Status != TransactionStatus.Aborted) + if (promoteException != null) { - throw SQL.PromotionFailed(promoteException); + try + { + // Safely access Transaction status - as it's possible Transaction is not in right state. + if (Transaction?.TransactionInformation?.Status != TransactionStatus.Aborted) + { + throw SQL.PromotionFailed(promoteException); + } + } + catch (TransactionException te) + { + SqlClientEventSource.Log.TryTraceEvent("SqlDelegatedTransaction.Promote | RES | CPOOL | Object Id {0}, Client Connection Id {1}, Transaction exception occurred: {2}.", ObjectID, usersConnection?.ClientConnectionId, te.Message); + // Throw promote exception if transaction state is unknown. + throw SQL.PromotionFailed(promoteException); + } } else { diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlDelegatedTransaction.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlDelegatedTransaction.cs index 7bf191e837..10ec781f30 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlDelegatedTransaction.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlDelegatedTransaction.cs @@ -255,9 +255,22 @@ public Byte[] Promote() } //Throw exception only if Transaction is still active and not yet aborted. - if (promoteException != null && Transaction.TransactionInformation.Status != SysTx.TransactionStatus.Aborted) + if (promoteException != null) { - throw SQL.PromotionFailed(promoteException); + try + { + // Safely access Transction status - as it's possible Transaction is not in right state. + if (Transaction?.TransactionInformation?.Status == SysTx.TransactionStatus.Aborted) + { + throw SQL.PromotionFailed(promoteException); + } + } + catch (SysTx.TransactionException te) + { + SqlClientEventSource.Log.TryTraceEvent("SqlDelegatedTransaction.Promote | RES | CPOOL | Object Id {0}, Client Connection Id {1}, Transaction exception occurred: {2}.", ObjectID, usersConnection?.ClientConnectionId, te.Message); + // Throw promote exception if transaction state is unknown. + throw SQL.PromotionFailed(promoteException); + } } else { From 02d74740932b28d6f4a8abb38ffbaf9a86690de3 Mon Sep 17 00:00:00 2001 From: Kaur-Parminder Date: Fri, 17 Sep 2021 12:50:46 -0700 Subject: [PATCH 2/2] Porting orginal issue review changes:Add missing logs --- .../src/Microsoft/Data/SqlClient/SqlDelegatedTransaction.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlDelegatedTransaction.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlDelegatedTransaction.cs index d2ae5d031c..3c289bb790 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlDelegatedTransaction.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlDelegatedTransaction.cs @@ -179,6 +179,8 @@ public byte[] Promote() { promoteException = e; + ADP.TraceExceptionWithoutRethrow(e); + // Doom the connection, to make sure that the transaction is // eventually rolled back. // VSTS 144562: doom the connection while having the lock on it to prevent race condition with "Transaction Ended" Event @@ -187,6 +189,7 @@ public byte[] Promote() catch (InvalidOperationException e) { promoteException = e; + ADP.TraceExceptionWithoutRethrow(e); connection.DoomThisConnection(); } } @@ -367,6 +370,8 @@ public void SinglePhaseCommit(SinglePhaseEnlistment enlistment) { commitException = e; + ADP.TraceExceptionWithoutRethrow(e); + // Doom the connection, to make sure that the transaction is // eventually rolled back. // VSTS 144562: doom the connection while having the lock on it to prevent race condition with "Transaction Ended" Event @@ -375,6 +380,7 @@ public void SinglePhaseCommit(SinglePhaseEnlistment enlistment) catch (InvalidOperationException e) { commitException = e; + ADP.TraceExceptionWithoutRethrow(e); connection.DoomThisConnection(); } if (commitException != null)