File mono-19955-fix.patch of Package mono
diff -Nruw mono-6.12.0.182-orig/mcs/class/System.Transactions/System.Transactions/Transaction.cs mono-6.12.0.182/mcs/class/System.Transactions/System.Transactions/Transaction.cs
--- mono-6.12.0.182-orig/mcs/class/System.Transactions/System.Transactions/Transaction.cs 2022-06-14 22:36:01.000000000 +0200
+++ mono-6.12.0.182/mcs/class/System.Transactions/System.Transactions/Transaction.cs 2022-06-26 08:17:32.744094086 +0200
@@ -23,6 +23,8 @@
[ThreadStatic]
static Transaction ambient;
+ Transaction internalTransaction;
+
IsolationLevel level;
TransactionInformation info;
@@ -83,6 +85,8 @@
volatiles = other.Volatiles;
durables = other.Durables;
pspe = other.Pspe;
+ TransactionCompletedInternal = other.TransactionCompletedInternal;
+ internalTransaction = other;
}
[MonoTODO]
@@ -92,7 +96,26 @@
throw new NotImplementedException ();
}
- public event TransactionCompletedEventHandler TransactionCompleted;
+ internal event TransactionCompletedEventHandler TransactionCompletedInternal;
+
+ public event TransactionCompletedEventHandler TransactionCompleted
+ {
+ add
+ {
+ if(this.internalTransaction != null)
+ this.internalTransaction.TransactionCompleted += value;
+
+ TransactionCompletedInternal += value;
+ }
+
+ remove
+ {
+ if(this.internalTransaction != null)
+ this.internalTransaction.TransactionCompleted -= value;
+
+ TransactionCompletedInternal -= value;
+ }
+ }
public static Transaction Current {
get {
@@ -378,7 +401,7 @@
private void DoCommit ()
{
/* Scope becomes null in TransactionScope.Dispose */
- if (Scope != null) {
+ if (Scope != null && (!Scope.IsComplete || !Scope.IsDisposed)) {
/* See test ExplicitTransaction8 */
Rollback (null, null);
CheckAborted ();
@@ -529,20 +552,21 @@
void CheckAborted ()
{
- if (aborted)
+ if (aborted || (Scope != null && Scope.IsAborted))
throw new TransactionAbortedException ("Transaction has aborted", innerException);
}
void FireCompleted ()
{
- if (TransactionCompleted != null)
- TransactionCompleted (this, new TransactionEventArgs(this));
+ if (TransactionCompletedInternal != null)
+ TransactionCompletedInternal (this, new TransactionEventArgs(this));
}
static void EnsureIncompleteCurrentScope ()
{
if (CurrentInternal == null)
return;
+
if (CurrentInternal.Scope != null && CurrentInternal.Scope.IsComplete)
throw new InvalidOperationException ("The current TransactionScope is already complete");
}
diff -Nruw mono-6.12.0.182-orig/mcs/class/System.Transactions/System.Transactions/TransactionScope.cs mono-6.12.0.182/mcs/class/System.Transactions/System.Transactions/TransactionScope.cs
--- mono-6.12.0.182-orig/mcs/class/System.Transactions/System.Transactions/TransactionScope.cs 2022-06-14 22:36:01.000000000 +0200
+++ mono-6.12.0.182/mcs/class/System.Transactions/System.Transactions/TransactionScope.cs 2022-06-26 09:17:38.574386820 +0200
@@ -9,7 +9,7 @@
// (C)2006 Novell Inc,
//
-
+using System.Threading;
using DTCOption = System.Transactions.EnterpriseServicesInteropOption;
namespace System.Transactions
@@ -19,6 +19,7 @@
static TransactionOptions defaultOptions =
new TransactionOptions (0, TransactionManager.DefaultTimeout);
+ Timer scopeTimer;
Transaction transaction;
Transaction oldTransaction;
TransactionScope parentScope;
@@ -29,6 +30,7 @@
bool disposed;
bool completed;
+ bool aborted;
bool isRoot;
bool asyncFlowEnabled;
@@ -99,7 +101,7 @@
DTCOption interopOption)
{
Initialize (scopeOption, null, transactionOptions, interopOption,
- TransactionManager.DefaultTimeout, TransactionScopeAsyncFlowOption.Suppress);
+ transactionOptions.Timeout, TransactionScopeAsyncFlowOption.Suppress);
}
public TransactionScope (Transaction transactionToUse,
@@ -143,6 +145,34 @@
transaction.InitScope (this);
if (parentScope != null)
parentScope.nested ++;
+
+ if(this.timeout != TimeSpan.Zero)
+ scopeTimer = new Timer(TransactionScope.TimerCallback, this, scopeTimeout, TimeSpan.Zero);
+ }
+
+ private static void TimerCallback(object state)
+ {
+ TransactionScope scope = state as TransactionScope;
+ if ( null == scope )
+ {
+ throw new TransactionException( "TransactionScopeTimerObjectInvalid", null );
+ }
+
+ scope.TimeoutScope();
+ }
+
+ private void TimeoutScope()
+ {
+ if ( ( !this.completed ) && ( null != this.transaction ) )
+ {
+ try
+ {
+ this.transaction.Rollback();
+ this.aborted = true;
+ }
+ catch ( ObjectDisposedException ex ) { }
+ catch ( TransactionException txEx ) { }
+ }
}
Transaction InitTransaction (Transaction tx, TransactionScopeOption scopeOption, TransactionOptions options)
@@ -176,11 +206,21 @@
public void Complete ()
{
if (completed)
+ {
throw new InvalidOperationException ("The current TransactionScope is already complete. You should dispose the TransactionScope.");
+ }
completed = true;
}
+ internal bool IsAborted {
+ get { return aborted; }
+ }
+
+ internal bool IsDisposed {
+ get { return disposed; }
+ }
+
internal bool IsComplete {
get { return completed; }
}
@@ -205,6 +245,7 @@
throw new InvalidOperationException ("TransactionScope nested incorrectly");
}
+
if (Transaction.CurrentInternal != transaction && !asyncFlowEnabled) {
if (transaction != null)
transaction.Rollback ();
@@ -214,6 +255,9 @@
throw new InvalidOperationException ("Transaction.Current has changed inside of the TransactionScope");
}
+ if (scopeTimer != null)
+ scopeTimer.Dispose();
+
if (asyncFlowEnabled) {
if (oldTransaction != null)
oldTransaction.Scope = parentScope;
@@ -226,10 +270,12 @@
variedTransaction.Scope = parentScope;
Transaction.CurrentInternal = oldTransaction;
-
transaction.Scope = null;
- if (!IsComplete) {
+ if (IsAborted) {
+ throw new TransactionAbortedException("Transaction has aborted");
+ }
+ else if (!IsComplete) {
transaction.Rollback ();
variedTransaction.Rollback();
return;
@@ -251,8 +297,10 @@
/* scope was not in a transaction, (Suppress) */
return;
+ if (IsAborted) {
transaction.Scope = null;
-
+ throw new TransactionAbortedException("Transaction has aborted");
+ }
if (!IsComplete)
{
transaction.Rollback();
@@ -265,6 +313,7 @@
transaction.CommitInternal();
+ transaction.Scope = null;
}
}